LISP:函数位置的非法参数

LISP: Illegal argument in functor position

我的代码如下所示:

(defmacro createList (a b c)
  (let ((lst (list a b c)))
    (write lst)))

(createList 1 2 3 )

我得到:

Illegal argument in functor position: 1 in (1 2 3).

我知道这里有一个类似的问题: Lisp Illegal argument in functor position

但是我无法调整我的问题的答案。括号问题在哪里?我做错了什么?

write 函数的结果是它的参数。因此,(write "Tom") 的结果是 "Tom"(它写入输出流的事实是该函数的副作用)。

宏return要计算的形式,通常表示列表。

您的宏创建列表 (1 2 3),然后将其写出。 write 是在宏扩展时计算的,而不是 "runtime"。因为 write returns 它的参数是它的 return 值,而 write 是最后调用的函数,宏函数的结果是 [=12= 的结果] 函数,或者,在本例中,(1 2 3).

然后计算

(1 2 3),但是如果您尝试在顶层键入 (1 2 3),它会将 1 视为表单的第一个参数,并尝试将其作为一个函数进行评估——它不是,它只是数字 1.

如果你想看看你的宏会展开什么,你可以试试:(macroexpand '(createlist 1 2 3))

你可以看到下面的结果:

[2]> (macroexpand '(createlist 1 2 3))
(1 2 3)
(1 2 3) ;
T

您看到第一个 (1 2 3),这是您 write 的结果。然后您会看到第二个 (1 2 3),它是宏展开的结果(上面讨论过),紧接着是 T,它是 macroexpand 函数的结果。

这就是正在发生的事情。不清楚如何修复它,因为不清楚你想做什么。

也许这就是您想要做的:

(defmacro createlist (a b c)
  `(list ,a ,b ,c))

[5]> (macroexpand `(createlist 1 2 3))
(LIST 1 2 3) ;
T

write returns 作为第一个参数传递给它的对象。因此,您从宏中 returning lst。无论你从宏中 return 都被认为是 lisp 代码。

当运行你的代码时,你应该看到

(1 2 3)

在错误之前的标准输出上。这就是你给 write 的结果: (list a b c)a 绑定到 1 等的结果

lisp 代码中列表的第一个元素是被调用的函数。显然,作为此列表的第一个元素的 1 不是函数。

为了调试此类错误,使用 macroexpand 通常很有帮助:

(defmacro createList (a b c)
  (let ((lst (list a b c)))
     (write lst)))

(format t "~%Expanded ~a~%" (macroexpand-1 '(createList 1 2 3)))

(Live)