Почему не работает применение функции, возвращаемой макросом elisp? - PullRequest
8 голосов
/ 22 июня 2011

Например, вот макрос:

(defmacro my-macro (x y)
  (if (> x 0) 
  `(lambda (z) (+ z ,y))
`(lambda (z) (+ ,x z))))

и (my-macro 2 3) возвращает (lambda (z) (+ z 3))

Однако ((my-macro 2 3) 1) возвращает сообщение об ошибке,

 Debugger entered--Lisp error:

 (invalid-function (my-macro 2 3))
  ((my-macro 2 3) 1)
  eval(((my-macro 2 3) 1))
  eval-last-sexp-1(nil)
  eval-last-sexp(nil)
  call-interactively(eval-last-sexp nil nil)

Чего мне не хватает?

Ответы [ 2 ]

7 голосов
/ 22 июня 2011

Emacs Lisp требует, чтобы первый элемент списка form был встроенной функцией (или subr ), лямбда-выражением (т.е. (lambda LIST . LIST)) или макрос лямбда-выражения (т.е. (macro lambda LIST . LIST)).Первым элементом также может быть символ , слот функции которого содержит допустимый первый элемент.

(my-macro 2 3) не имеет требуемой формы, поэтому это недопустимая функция.

Если вы привыкли к Scheme, где функциональная часть вызова функции оценивается нормально, обратите внимание, что это не может работать одинаково в Лиспе, где функции имеют другое пространство имен ((f 3) ищет функцию fslot, тогда как значение f обычно является его значением slot.)

Если вы хотите оценить функцию как нормальное значение, вы можете использовать funcall или apply.

(funcall (my-macro 2 3) 1)
0 голосов
/ 22 июня 2011

Как видно из сообщения об ошибке, при оценке формы ((my-macro 2 3) 1) Emacs не раскрывает (my-macro 2 3) перед оценкой списка, первым элементом которого является.Вы хотите сказать

(funcall (my-macro 2 3) 1)

или

(eval (list (my-macro 2 3) 1)

или что-то в этом роде, чтобы макрос был оценен.

...