4
votes

Little help here please . I am trying to create this lisp macro which takes a list (of numbers) as input and returns the sum of those numbers. The code

(setf g (list 1 2 3 4))

(defmacro add-test(var)
    `(+ ,@var))

(add-test g) gives this error

The value G is not of type LIST.
[Condition of type TYPE-ERROR]

At the same time (add-test (1 2 3 4)) gives the correct result which is 10.

Can you please explain , why is it not working when variable is passed in to the function?

Other details -

Lispbox - SBCL

Ubuntu Linux

Thanks in advance

1

1 Answers

10
votes

That's easy and one of the most common macro questions.

(add-test g)

Now on macro expansion, the macro ADD-TEST is called with the parameter VAR getting the value G, a symbol.

Then you try a list operation. The backquote expression

`(+ ,@var)

The value of VAR is G, and you try to splice that into the list (+ ... ). Now the returned expression is (+ . G).

CL-USER 12 > (macroexpand '(add-test g))
(+ . G)
T

(+ . G) is not a valid Lisp form. It's not valid source code.

Remember, the parameters to a Macro are the unevaluated source expressions.

Compare that with the following:

CL-USER 13 > (macroexpand '(add-test (1 2 3 4)))
(+ 1 2 3 4)
T

You said: 'Can you please explain, why is it not working when variable is passed in to the function?'

Remember, ADD-TEST is NOT a function, it is a macro. A macro gets the source code passed and returns a new form - that form is then later evaluated.