А не задумывались ли вы, что quote и lambda по сути ничем не отличаются. Я тут сразу отбрасываю математический смысл, лексическую область и прочее, это непосредственно к лиспу отношения не имеет. Например
(define a (quote 1))
(define a (lambda() 1))
(eval a)
(a)
Тут одна и та же семантика. Просто задержка вычислений. Разница в том, что quote принимает только 1 аргумент. Я давно думал об этом, с помощью лямбд можно эмулировать поведение quote. В picolisp, собственно, и нет разницы, там lambda вообще выкинута. Понятное дело, что сейчас, в связи с модой на ФП, с лямбдой связывают кучу всяких заклинаний. Но ведь вплоть до схемы этой всей ФП-лабуды в лиспах не было. Получается, что Маккарти ввел лишнюю сущность в язык. Этот вопрос где нибудь обсуждается? Кто-нибудь видел какие-нибудь бумаги? Может быть, это было простой ошибкой дизайна, которую не успели выпилить и она исторически прижилась?
Так я не претендую на истину, я ж говорю, что вообще не знаю пику и хотел бы разобраться как там устроено. Но ТС нормально объяснить не может, по пунктам, как раскрывается quote, как записывается анонимная функция, я по его словам прав, но выводы делаю неверные. Очень интересно знать, почему и в какой момент я ошибся.
Мне вдруг пришло в голову, что там все хитрее, и лямбда это не (lambda (x) ...), а ((x) ...). То есть (quote (x) ...) -> ((x) ...), а уже это в свою очередь соответствует лямбде. И дело не в квоте а в автоподставлении лямбды в начало списка.
Странный у тебя подход. Там вся фишка в том, что код самомодифицирует себя сам во время исполнения. Там нет не лупа не рекурсии. А ты что написал? Ты поведение чего тут реализовал? Ну напиши тогда while true (counter++) (print counner))))):)
Переменная такая же — такой-то список в котором код print и код модификации этого же списка, разница в том, что в CL она вычисляется нормально — в список, а там особый вычислитель который делает с таким кодом странные вещи, я такой вычислитель не пишу (можно было бы и написать), а просто по мелочи на каждое странное поведение — вот так или (loop (eval.
Вообще мне не понятно, как безобидный push в конце функции должен превращать её в рекурсивную — это же бред :) Ну как если бы в си умудриться переписать ret на jmp в начало.
Нет там особого вычислителя. Обычный интерпретатор. Это код как данные в действии.
должен превращать её в рекурсивную
Он не превращает ее в рекурсивную, в твоем понимании, она не использует стек вызовов. Но она делает то, что требуется. Перед каждым вызовом она модифицирует свое тело так как нужно.
REPL крутит многократно — он REP_Loop_, ну и он тут не нужен, тут про R_Eval_PL — Quote и lambda (комментарий), начинает выполнять и подкидывает сам себе кода (и выкидывает), так что печать продолжается и продолжается.
Вообще мне не понятно, как безобидный push в конце функции должен превращать её в рекурсивную — это же бред
Тоже долго не мог врубиться, но щас доперло, кажется.
На первом шаге исполняется print внутри которой меняется и сразу выводится counter. Затем, вся форма бегин, с содержимым дублируется в конец функции, после самой же begin. проверяется длина списка, в оригинале она 2 - скобки и сама форма. После инструкции push она становиться 3. проверяем - норм. Pop не срабатывает. Flow переходит к следующей begin, делается все то же самое, только длина теперь больше 3-х, роp отработал, убрал первый бегин. И понеслась. ГЕНИАЛЬНО!
превращать её в рекурсивную
Там вообще выход из функции не происходит, не то что рекурсивные вызовы.