Основная ошибка макроса Lisp - PullRequest
       8

Основная ошибка макроса Lisp

3 голосов
/ 21 сентября 2010

Небольшая помощь здесь, пожалуйста. Я пытаюсь создать этот макрос LISP, который принимает список (чисел) в качестве входных данных и возвращает сумму этих чисел. Код

(setf g (list 1 2 3 4))

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

(add-test g) выдает эту ошибку

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

В то же время (add-test (1 2 3 4)) дает правильный результат, равный 10.

Не могли бы вы объяснить, почему это не работает, когда переменная передается в функцию?

Другие детали -

Lispbox - SBCL

Ubuntu Linux

Заранее спасибо

1 Ответ

9 голосов
/ 21 сентября 2010

Это просто и один из самых распространенных вопросов макроса.

(add-test g)

Теперь при расширении макроса, макрос ADD-TEST вызывается с параметром VAR, получая значение G, символ.

Затем вы пытаетесь выполнить операцию со списком. Выражение обратной цитаты

`(+ ,@var)

Значение VAR равно G, и вы пытаетесь объединить его в список (+ ... ). Теперь возвращаемое выражение (+ . G).

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

(+ . G) не является допустимой формой Lisp. Это неверный исходный код.

Помните, что параметры макроса являются неоцененными исходными выражениями.

Сравните это со следующим:

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

Вы сказали: «Не могли бы вы объяснить, почему это не работает, когда переменная передается в функцию?»

Помните, ADD-TEST это НЕ функция, это макрос. Макрос получает переданный исходный код и возвращает новую форму - эта форма затем анализируется.

...