阅读this question让我思考什么构成了一个有效的表达方式。显然,可以使用常规语法来“调用”符号和lambda。根据{{3}},
功能名称。 1.(在环境中)作为该环境中函数名称的符号或列表(setf符号)。 2.符号或列表(setf符号)。
因此,从理论上讲,(setf some-name)
是一个函数名。我决定尝试一下。
(defun (setf try-this) ()
(format t "Don't name your functions like this, kids :)"))
((setf try-this))
(funcall '(setf try-this))
(setf (try-this))
GNU CLISP,SBCL和ABCL都将让我定义此功能。但是,SBCL和ABCL不允许我使用代码段中显示的任何语法来称呼它。另一方面,CLISP将在前两个运行,但在第三个仍会出错。
我很好奇哪个编译器的行为正确。既然SBCL和ABCL都同意,我可能会猜测一个正确的实现应该拒绝该代码。第二个问题是,由于上面的操作无法移植,我将如何从代码片段中调用我难以置信的,无用的函数。或者,也许更有用的是
答案 0 :(得分:5)
SETF
函数必须至少接受一个参数,这是要存储在该位置的新值。也可能需要其他参数,这些参数将从调用SETF
的place表达式中的参数中填充。
使用SETF
时,它必须具有偶数个参数:要分配给的每个位置都需要分配一个值。
应该是:
(defun (setf try-this) (new-value)
(format t "You tried to store ~S~%" new-value))
(setf (try-this) 3)
(funcall #'(setf try-this) 'foo)
您不能使用
((setf try-this) 'bar)
因为表单的car
不包含函数名称。它只能是符号或lambda表达式(尽管实现可能允许其他格式作为扩展名。)