LINUX.ORG.RU

Quote и lambda

 


1

1

А не задумывались ли вы, что quote и lambda по сути ничем не отличаются. Я тут сразу отбрасываю математический смысл, лексическую область и прочее, это непосредственно к лиспу отношения не имеет. Например

(define a (quote 1))
(define a (lambda() 1))

(eval a)
(a)
Тут одна и та же семантика. Просто задержка вычислений. Разница в том, что quote принимает только 1 аргумент. Я давно думал об этом, с помощью лямбд можно эмулировать поведение quote. В picolisp, собственно, и нет разницы, там lambda вообще выкинута. Понятное дело, что сейчас, в связи с модой на ФП, с лямбдой связывают кучу всяких заклинаний. Но ведь вплоть до схемы этой всей ФП-лабуды в лиспах не было. Получается, что Маккарти ввел лишнюю сущность в язык. Этот вопрос где нибудь обсуждается? Кто-нибудь видел какие-нибудь бумаги? Может быть, это было простой ошибкой дизайна, которую не успели выпилить и она исторически прижилась?


Ответ на: комментарий от quasimoto
(defparameter *counter* 0)

(defparameter code-as-data
  '((format t "~S~%" (incf *counter*))
    (push (first code-as-data) code-as-data)
    (when (> (length code-as-data) 3) (pop code-as-data))))

(loop (eval `(progn ,@code-as-data)))
; 1
; 2
; ...

А ещё чтобы получить идиотское поведение можно написать идиотский интерпретатор, да.

quasimoto ★★★★
()
Ответ на: комментарий от anonymous

Так я не претендую на истину, я ж говорю, что вообще не знаю пику и хотел бы разобраться как там устроено. Но ТС нормально объяснить не может, по пунктам, как раскрывается quote, как записывается анонимная функция, я по его словам прав, но выводы делаю неверные. Очень интересно знать, почему и в какой момент я ошибся.

staseg ★★★★★
()
Ответ на: комментарий от staseg

Мне вдруг пришло в голову, что там все хитрее, и лямбда это не (lambda (x) ...), а ((x) ...). То есть (quote (x) ...) -> ((x) ...), а уже это в свою очередь соответствует лямбде. И дело не в квоте а в автоподставлении лямбды в начало списка.

anonymous
()
Ответ на: комментарий от staseg

Ой, действительно :) Был пьян и не заметил твоего поста/

anonymous
()
Ответ на: комментарий от quasimoto

Странный у тебя подход. Там вся фишка в том, что код самомодифицирует себя сам во время исполнения. Там нет не лупа не рекурсии. А ты что написал? Ты поведение чего тут реализовал? Ну напиши тогда while true (counter++) (print counner))))):)

anonymous
()
Ответ на: комментарий от anonymous

Переменная такая же — такой-то список в котором код print и код модификации этого же списка, разница в том, что в CL она вычисляется нормально — в список, а там особый вычислитель который делает с таким кодом странные вещи, я такой вычислитель не пишу (можно было бы и написать), а просто по мелочи на каждое странное поведение — вот так или (loop (eval.

Вообще мне не понятно, как безобидный push в конце функции должен превращать её в рекурсивную — это же бред :) Ну как если бы в си умудриться переписать ret на jmp в начало.

quasimoto ★★★★
()
Последнее исправление: quasimoto (всего исправлений: 1)
Ответ на: комментарий от quasimoto

Переменная такая же

За нее речи нет. Да она такая же.

особый вычислитель

Нет там особого вычислителя. Обычный интерпретатор. Это код как данные в действии.

должен превращать её в рекурсивную

Он не превращает ее в рекурсивную, в твоем понимании, она не использует стек вызовов. Но она делает то, что требуется. Перед каждым вызовом она модифицирует свое тело так как нужно.

anonymous
()
Ответ на: комментарий от anonymous

вычислитель

интерпретатор

Ну да.

Он не превращает ее в рекурсивную

Я знаю, интерпретатор рекурсивный/цикличный/whatever — как-то он же крутит f.

Перед каждым вызовом она модифицирует свое тело так как нужно.

Вызов всего один же — зачем тогда оно вызывается снова и снова? Потому что новый код запушили? Фигню они придумали :)

Где-то кроме ${foo}lisp такое ещё есть?

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

как-то он же крутит f.

Он крутит однократно, как любой репл. Он не зацикливает, только ожидает ввода и выплевывает результат.

Где-то кроме ${foo}lisp такое ещё есть?

В любом ЯП с полноценной поддержкой рефлексии, наверное.

anonymous
()
Ответ на: комментарий от anonymous

Он крутит однократно, как любой репл

REPL крутит многократно — он REP_Loop_, ну и он тут не нужен, тут про R_Eval_PL — Quote и lambda (комментарий), начинает выполнять и подкидывает сам себе кода (и выкидывает), так что печать продолжается и продолжается.

quasimoto ★★★★
()
Ответ на: комментарий от quasimoto

REPL крутит многократно

Да, многократно, но каждая итерация требует ввода текста на вход.

подкидывает сам себе кода

Да этот код и есть ввод текста, поэтому он и зацикливает репл, он постоянно кидает в него дровишки.

anonymous
()
Ответ на: комментарий от elyadow

Очевидно же, что кусок говна elyadow, пидарас phill, гнида avtoritetniy-expert и упоротый уебан anonimous - это одно и то же ничтожное школоло.

anonymous
()
Ответ на: комментарий от anonymous

Мы тебя вчера только вчетвером ебали? Там же еще кто-то был, ты забыл просто, человека 3 еще точно было.

anonymous
()
Ответ на: комментарий от quasimoto

Вообще мне не понятно, как безобидный push в конце функции должен превращать её в рекурсивную — это же бред

Тоже долго не мог врубиться, но щас доперло, кажется. На первом шаге исполняется print внутри которой меняется и сразу выводится counter. Затем, вся форма бегин, с содержимым дублируется в конец функции, после самой же begin. проверяется длина списка, в оригинале она 2 - скобки и сама форма. После инструкции push она становиться 3. проверяем - норм. Pop не срабатывает. Flow переходит к следующей begin, делается все то же самое, только длина теперь больше 3-х, роp отработал, убрал первый бегин. И понеслась. ГЕНИАЛЬНО!

превращать её в рекурсивную

Там вообще выход из функции не происходит, не то что рекурсивные вызовы.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.