macro expansion: to quote the body forms or not?
Asked Answered
U

1

3

I'm having a hard time understanding exactly how macro expansion works. What is the difference in how the elisp interpreter handles these two snippets of code?

(defmacro foo (arg)
  (message "arg is: %s" arg))
(foo "bar")

and:

(defmacro foo (arg)
  `(message "arg is: %s" ,arg))
(foo "bar")
Unwinking answered 13/6, 2013 at 17:18 Comment(0)
G
7

You example may be confusing because

  1. message both displays a message and returns it.
  2. strings (like "bar") are self-evaluating.

Instructive Example

(defconst zzz 123)
(defmacro zzz1 (arg)
  `(insert (format "arg is: %s" ,arg)))
(defmacro zzz2 (arg)
  (insert (format "arg is: %s" arg)))

Evaluate the code above using C-x C-e after each of the 3 forms.

Now evaluate these:

First version: (zzz1 zzz)

The interpreter...

  1. calls the macro function of zzz1
  2. the macro function returns the form (insert (format "arg is: %s" zzz))
  3. the interpreter evaluates the form, and inserts "arg is: 123" into the current buffer, and returns nil (seen in the echo area at the bottom)

Second version: (zzz2 zzz)

The interpreter...

  1. calls the macro function of zzz2
  2. the macro function inserts "arg is: zzz" in the current buffer and returns nil
  3. the interpreter evaluates nil to nil (seen in the echo are at the bottom)

The bottom line

The most important "take-away" here is that macros are just functions which operate on code before the interpreter (of compiler) kicks in.

These functions take their arguments unevaluated (i.e., in both zzz1 and zzz2, arg is zzz, not 123).

They are evaluated like any other lisp function (e.g., they can have macro forms in their bodies; the body is wrapped in an implicit progn; &c).

Their return value is evaluated by the interpreter instead of the original form.

Gilding answered 13/6, 2013 at 17:36 Comment(1)
It's the two rounds of evaluation that threw me off. I thought it behaved like the C preprocessor -- that there was only one round of evaluation. My mistaken mental model was that the macro invocation (zzz2 zzz) was replaced by (insert (format "arg is: %s" zzz)) (the body of the macro but with the args substituted), then evaluated.Unwinking

© 2022 - 2024 — McMap. All rights reserved.