在测试lisp函数时,我在列表中进行了硬编码。这在使用pop
时生成了跟随错误:
(pop '(1 2 3))
EVAL:1不是函数名称;尝试使用符号
然而,使用car
可以正常工作:
(car'(1 2 3))
> 1
我认为这是因为pop
需要一个变量,它可以重新存储列表的其余部分。
如果是这样,当前的错误消息来自哪里,为什么它如此令人难以置信的无益?它甚至没有提到pop
是问题所在。
答案 0 :(得分:6)
预定义的宏pop
采用参数而不是列表值,而是place,这是一个评估到某个位置的表单(有关一般说明,请参阅Hyperspec)。例如:
CL-USER> (let ((stack '(1 2 3)))
(print (pop stack))
(print stack)
"Done!")
1
(2 3)
"Done!"
出于错误消息的原因:car
将参数作为参数列表,因此'(1 2 3)
是一个引用形式,当评估时,会生成列表{{ 1}};最后,(1 2 3)
返回此列表的第一个元素1
。如果car
是宏,而不是函数,则pop
形式的扩展类似于:
(pop '(1 2 3))
您可以从中看到列表(LET* ((#:G10655 (1 2 3)) ...)
被评估,这会产生错误消息:
EVAL:1不是函数名称;尝试使用符号
实际上,在此评估中,(1 2 3)
被视为一个表单,系统会尝试将函数(1 2 3)
应用于参数1
,这是一个错误,因为{ {1}}不是函数。
无用的消息是典型的带有宏的语言,当错误发生在宏扩展阶段之后:因此使用2 3
之类的工具非常有用允许查看此阶段的结果,如@jkiiski在评论中建议的1
。