Why doesn't application of function returned by elisp macro work?
For example, here is a macro:
(defmacro my-macro (x y)
(if (> x 0)
`(lambda (z) (+ z ,y))
`(lambda (z) (+ ,x z))))
and (my-macro 2 3)
return开发者_如何学JAVAs (lambda (z) (+ z 3))
However, ((my-macro 2 3) 1)
returns an error saying,
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)
What am I missing?
Emacs Lisp requires the first element of a list form to be a built-in function (or subr), a lambda-expression (i.e. (lambda LIST . LIST)
) or a macro lambda-expression (i.e. (macro lambda LIST . LIST)
). The first element can also be a symbol whose function slot contains a valid first element.
(my-macro 2 3)
doesn't have the required form, so it's an invalid function.
If you're used to Scheme, where the function part of a function call is evaluated normally, note that this can't work identically in Lisp where functions have a different namespace ((f 3)
looks up f
's function slot, whereas the value of f
is normally its value slot).
If you want to evaluate a function like a normal value, you can use funcall
or apply
.
(funcall (my-macro 2 3) 1)
As the error message makes clear, in evaluating the form ((my-macro 2 3) 1)
, Emacs doesn't expand (my-macro 2 3)
before evaluating the list it's the first element of. You want to say
(funcall (my-macro 2 3) 1)
or
(eval (list (my-macro 2 3) 1)
or something like that, so that the macro gets evaluated.
精彩评论