普通 lisp 中返回 Lambda 的宏不起作用

Lambda-returning macro in common lisp does not work

我想创建一个 returns lambda 的宏,但我总是遇到编译错误。 当您对常规 lambda 进行宏扩展时,您会得到以下内容:

(print (macroexpand '(LAMBDA (X) (+ 1 X))))

=> #'(LAMBDA (X) (+ 1 X)) 

现在,假设我想创建一个扩展为 lambda 的宏,例如:

(defmacro test (x) `(lambda (x) (+ 1 x)))

如果我打印那个宏的扩展,我得到预期的扩展:

(print (macroexpand '(test x)))

=> #'(LAMBDA (X) (+ 1 X))

与常规 lambda 完全相同。 但是当我尝试使用“test”宏时,我仍然必须使用“funcall”才能使其工作。

(print ((LAMBDA (X) (+ 1 X)) 1))
=> 2

(print (funcall (test x) 1))
=> 2

(print ((test x) 1))

=>  Execution of a form compiled with errors.
Form:
  ((TEST X) 1)
Compile-time error:
  illegal function call

这怎么可能?

test宏扩展为普通的lambda,我的理解是扩展后lisp应该不知道它是宏来的,应该和lambda没有区别。 common lisp 如何在不使用“funcall”的情况下在表达式的运算符位置使用常规 lambda,我该怎么做? 有人知道这里发生了什么吗?

表达式的运算符位置不被视为表达式,因此它不会像参数那样进行宏扩展。

它适用于 LAMBDA,因为运算符位置的语法特别允许那里的 lambda 表达式。事实上,有一个名为 LAMBDA 的宏是巧合,它不是用来实现这个的。它在 Lambda Forms:

的 CLHS 描述中指定

A lambda form is similar to a function form, except that the function name is replaced by a lambda expression.

Lambda 形式主要是与早期方言兼容的遗留功能。 LAMBDA 宏是 Common Lisp 的一项创新,它的创建只是为了方便,这样我们就不必在使用 lambda 表达式作为值时键入 #'。这与在 lambda 形式中使用 lambda 表达式无关。