Search code examples
macroscommon-lisplisp-macros

Why does the compilation of a Common Lisp macro in my environment produce a different result from the book? Is it possible to achieve the same?


I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.

In chapter 14, the last one, the author covers macros. In one section about compiling it, he mentions:

Since macro expansion can happen at any time, you should not write macros that produce side effects, such as assignments or i/o. But it’s fine for the macro to expand into an expression that produces side effects.

As a way to illustrate bad macros, he provides the following example:

(defmacro bad-announce-macro ()
 (format t "~%Hi mom!"))


(defun say-hi ()
 (bad-announce-macro))

> (compile ’say-hi)
Hi, mom!
SAY-HI

> (say-hi)
NIL

As I try to mimic the same in my environment, I have a different output:


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

As you see, when compiling the function, the Hi mom! part is missing.

Why does this happen? Is this just because of differences in Lisp implementations? Is it possible to achieve the same output?

I do not think it is the case, but I will put a printscreen from the book, in case this has to do with copying from a pdf and pasting in Emacs Slime's REPL.

enter image description here


Solution

  • SBCL by default already compiles definitions in the REPL. calling compile on an already compiled function then probably does nothing.

    The Hi, mom! message is already printed when the defun form gets executed. See your example above.

    Touretzky used for his book a different implementation, which used an interpreter in the REPL. The compiler would then invoked by the user via calling compile, compile-file, or similar.