0

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.

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

Comments

2

Your macro should expand to:

CL-USER 10 > (macroexpand '(two-from-one2 cons stack-overflow))
(CONS (QUOTE STACK-OVERFLOW) (QUOTE STACK-OVERFLOW))

So create lists with quote like this:

(defmacro two-from-one2 (func object)
  (list func (list 'quote object) (list 'quote object)))

Test:

CL-USER 9 > (two-from-one2 cons stack-overflow)
(STACK-OVERFLOW . STACK-OVERFLOW)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.