Здравствуйте, Александр!

Спасибо за комментарии!
Сделаю еще несколько заметок по теме.
Прошу прощения у тех, кому она неинтересна.

> В предыдущем письме вы привели пример кода на JavaScript, тем самым 
> подтолкнув меня в сторону императивной парадигмы. А там рекурсия бывает редко

Я дал пример на JavaScript, потому что у данного языка имеется
та конструкция, о которой говорил, при этом язык повсеместно
распространен, так что приведенными примерами можно реально
поиграть, даже не выходя из браузера с имейлом :)

При этом, конечно, о возможности решить те же самые задачи императивно
я намеренно забыл — ведь нужно было иллюстрировать функциональное
поведение, так что для явного выражения повторности ограничиваемся
рекурсией.

По поводу частоты циклов while в Си-подобных ЯП: вы привели статистику,
чтобы показать, что while встречается нередко, с чем я вполне согласен.
Но я и указывал на низкую частоту не употребления, а потребности в нем.
(Прошу, обратите внимание на мои слова, которые вы цитировали до
статистики.)  Дело в том, что нередко программист поленится выделить,
скажем, обновляющую часть и соответственно применить for, а оставит ее
в теле цикла while, который пришел ему в голову первым.  Но при этом
факт остается — по существу требовалось for, а не while.

Выражаясь крайным образом, можно сказать так: цикл с условием, но без
обновляющей части вообще невозможен, так как, если значения участвующих
в условии переменных не обновляются, цикл не завершится :)

А все это только в связи с тем, что наблюдаемое применение конструкций
не есть достаточный критерий их обоснованности или полезности.
Вокруг полно несоответствий между одним и другим — так и в
императивных, и в функциональных языках.

> Копипаст — зло.

В целом — да.  Но бывает и так, что копипаст сопровождается удалением
оригинала, т.е. имеет место не копирование, а перемещение.  И вообще,
даже избегая копипаст, сохранять «копипастуемость» частей программы
невредно.

Наконец, приведу еще две соображения в пользу безымянного самовызова.

Пусть мы написали функцию для чего-то — небольшую, но с рекурсией.
Хотелось бы функцию не именовать, так как она используется лишь в
одном месте, где она вызывается или передается как значение или
результат другой функции.  Но в отсутствии возможности безымянного
самовызова именовать требует рекурсия.  А потом вдруг спохватились,
что данная функция — всего лишь fold или zip и т.д., и переписали,
и уже именовать не требуется, так как и рекурсии нет.  Но тогда что
получается?  Именовать или нет зависит не от значительности функции
или других факторов, а полностью от наличия в ее реализации рекурсии.
Способ реализации диктует не относящиеся к реализации решения!

И последнее, представим, что безымянный вызов реализован в каком-то
языке в виде особой переменной: в нормальном случае, если эта
переменная встречается в теле функции, она соответствует вызову той
же функции.  Как и обсуждалось.  А теперь представим, что значение
этой переменной можно в явном виде задать при вызове функции —
каким-то особым дополнительным аргументом или вообще особым видом
вызова.  Теперь уже эта переменная будет соответствовать не вызванной
функции, а некоторой другой.  (Подразумевается, что возможность делать
такие особые вызовы тоже встроена в языке.)

Что получаем в итоге?
Если вызывать функцию обычным способом, через свою особую переменную
она будет вызывать себя.  А если значение этой переменной подменить
при помощи специального вызова, то уже вызывать она будет того, кого
ей указали.

Последнее знакомо?  Это как раз то преобразование функции, которое
мы делаем, чтобы к этой функции применить комбинатор Y или функцию,
которая сделает из нее ее мемо-вариант.  И Y, и мемо-генератор делают
свою работу вполне автономно, но им обоим нужно подать подходящим
образом уже преобразованную функцию.  А поскольку этот начальный шаг
пока делается вручную, ни нахождение неподвижной точки, ни переход
от функции к ее мемо-варианту не могут быть вполне автоматическими
процессами.  Мое предложение устраняет данное неудобство.  Понятно,
что его применимость этим не ограничена — оно скажется положительно
и на другие преобразования рекурсивных функций.

Вывод такой: обеспечение анонимного самовызова в свою очередь
открывает путь к дальнейшим усовершенствованиям языка.

Ответить