Sim
Sim

Reputation: 4184

Additional symbol LIST when using ,@

I observed a macro expansion I do not fully understand:

(defmacro test (cons-list)
  `(list
     ,@(mapcar #'(lambda(elem)
                   elem)
           cons-list)))


(defmacro test-2 ()
  `(list ,@(list (cons "a" "b"))))


(defmacro test-3 (cons-list)
  `(list ,@cons-list))

I'd expect both macros to expand in the same fashion, as I just use mapcar in a fancy way of creating the same list again and then use that list. But the results observed in SBCL are:

Why don't these macro expansions behave the same?

Upvotes: 1

Views: 53

Answers (1)

Svante
Svante

Reputation: 51501

Test-2 evaluates the form (list (cons "a" "b")), the other two do not.

Remember: the arguments to a macro are the forms read, unevaluated.

In order to get the same behaviour from test-2, you would have to quote the form: ,@'(list (cons "a" "b")).

EDIT: Here is a step-by-step expansion of test:

`(list
  ,@(mapcar #'(lambda (elem)
                elem)
            cons-list))

Removing the backquote syntactic sugar:

(list* 'list (mapcar #'(lambda (elem)
                         elem)
                     cons-list)

Argument substitution in your example:

(list* 'list (mapcar #'(lambda (elem)
                         elem)
                     '(list (cons "a" "b")))

Evaluate the mapcar form:

(list* 'list '(list (cons "a" "b")))

Evaluate the `list*' form:

'(list list (cons "a" "b"))

Upvotes: 2

Related Questions