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 the last chapter, on Macros, the author presents examples to re-write the built-in incf
macro. He teaches the concept with two different approaches: using back-quote notation and without it. Such as:
(defmacro list-notation-my-incf (x)
(list 'setq x (list '+ x 1)))
(defmacro backquote-notation-my-incf (x)
`(setq ,x (+ ,x 1)))
Later, the author introduces another example:
In the example below, TWO-FROM-ONE is a macro that takes a function name and another object as arguments; it expands into a call to the function with two arguments, both of which are the quoted object.
He only uses back-quote character to do it:
(defmacro two-from-one (func object)
`(,func ',object ',object))
And it works as expected:
CL-USER> (two-from-one cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)
Using slime-macroexpad-1
, I have:
(CONS 'STACK-OVERFLOW 'STACK-OVERFLOW)
As an exercise that I created for myself, I tried doing the same, but avoiding the back-quote notation. Unfortunately, I could not make it work:
(defmacro list-two-from-one (func object)
(list func (quote object) (quote object)))
Slime throws the error:
The variable OBJECT is unbound.
[Condition of type UNBOUND-VARIABLE]
Doing a macro expansion, I see:
(CONS OBJECT OBJECT)
If I try a different approach, it seems to be closer, but it does not work either:
(defmacro list-two-from-one (func object)
(list func object object))
Throws the error:
The variable STACK-OVERFLOW is unbound.
[Condition of type UNBOUND-VARIABLE]
And, finally, the macro expansion indicates:
(CONS STACK-OVERFLOW STACK-OVERFLOW)
I feel stuck. How do I successfully re-write the macro without using back-quote notation?
Thanks.
What you are looking for is something like
(defmacro list-two-from-one (func object)
(list func (list 'quote object) (list 'quote object)))
basically, the body of a macro should return the code, that, when evaluated, produces the desired result.
I.e., the macro body should produce (CONS 'STACK-OVERFLOW 'STACK-OVERFLOW)
.
Since 'a
is the same as (quote a)
, you want your macro to produce
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))
which is what my defmacro
above returns.