使用pop Lisp时未定义的函数错误

Riv*_*ver 0 list common-lisp

在测试lisp函数时,我在列表中进行了硬编码.然后在使用时生成以下错误pop:

(pop '(1 2 3))
Run Code Online (Sandbox Code Playgroud)

EVAL:1不是函数名称; 尝试使用符号代替

但是使用car工作正常:

(car'(1 2 3))
> 1
Run Code Online (Sandbox Code Playgroud)

我假设这是因为pop期望一个变量,它可以重新存储列表的其余部分.

如果是这样,当前的错误消息来自哪里,为什么它如此难以置信的无益?它甚至没有提到pop问题.

Ren*_*nzo 6

预定义的宏pop作为参数而不是列表值而是作为一个位置,即一个评估到位置的表单(有关一般说明,请参阅Hyperspec).例如:

CL-USER> (let ((stack '(1 2 3)))
           (print (pop stack))
           (print stack)
           "Done!")    

1 
(2 3) 
"Done!"
Run Code Online (Sandbox Code Playgroud)

出于错误消息的原因:car将列表作为参数,因此这'(1 2 3)是一个引用的形式,在评估时生成列表(1 2 3); 最后,此列表的第一个元素将1返回car.对于pop宏,而不是函数的情况,表单(pop '(1 2 3))有一个扩展,如下所示:

(LET* ((#:G10655 (1 2 3)) ...)
Run Code Online (Sandbox Code Playgroud)

从中您可以看到列表(1 2 3)已被评估,这会产生错误消息:

EVAL:1不是函数名称; 尝试使用符号代替

实际上,在此评估中,(1 2 3)将作为一个表单,系统尝试将该函数1应用于参数2 3,这是一个错误,因为1它不是一个函数.

当宏扩展阶段之后发生错误时,无用的消息是典型的带有宏的语言:因此,使用macroexpand允许查看此阶段结果的工具非常有用,如(macroexpand '(pop '(1 2 3)))@ jkiiski在评论中.