#macros #common-lisp #lisp-macros
Вопрос:
Я пытаюсь изучить общий шепелявый язык с помощью книги Общий шепелявый язык: мягкое введение в символические вычисления. Кроме того, я использую SBCL, Emacs и Slime.
В главе 14, последней, автор рассматривает макросы. В одном из разделов о его составлении он упоминает:
Поскольку расширение макросов может произойти в любое время, вам не следует писать макросы, которые вызывают побочные эффекты, такие как назначения или ввод-вывод. Но это нормально, если макрос расширяется до выражения, которое вызывает побочные эффекты.
Чтобы проиллюстрировать плохие макросы, он приводит следующий пример:
(defmacro bad-announce-macro ()
(format t "~%Hi mom!"))
(defun say-hi ()
(bad-announce-macro))
> (compile ’say-hi)
Hi, mom!
SAY-HI
> (say-hi)
NIL
Когда я пытаюсь воспроизвести то же самое в своей среде, у меня получается другой результат:
CL-USER> (defmacro bad-announce-macro ()
(format t "~%Hi mom!"))
BAD-ANNOUNCE-MACRO
CL-USER> (bad-announce-macro)
Hi mom!
NIL
CL-USER> (defun say-hi ()
(bad-announce-macro))
Hi mom!
SAY-HI
CL-USER> (say-hi)
NIL
CL-USER> (compile (say-hi))
; Evaluation aborted on #<UNDEFINED-FUNCTION NIL {100408C143}>.
CL-USER> (compile 'say-hi)
SAY-HI
NIL
NIL
CL-USER> (compile `say-hi)
SAY-HI
NIL
NIL
Как вы видите, при компиляции функции Hi mom!
часть отсутствует.
Почему это происходит? Это только из-за различий в реализациях Lisp? Возможно ли достичь того же результата?
Я не думаю, что это так, но я помещу распечатку из книги, на случай, если это связано с копированием из pdf и вставкой в РЕПЛ Emacs Slime.
Ответ №1:
SBCL по умолчанию уже компилирует определения в REPL. вызов compile
уже скомпилированной функции, вероятно, ничего не даст.
Hi, mom!
Сообщение уже распечатано, когда defun
форма будет выполнена. См.Ваш пример выше.
Турецкий использовал для своей книги другую реализацию, в которой использовался переводчик в REPL. Компилятор будет затем вызван пользователем с помощью вызова compile
compile-file
, или аналогично.