lisp - setf 函数名称

标签 lisp common-lisp setf

阅读 this question让我思考什么构成了表达式的有效汽车。显然,可以使用通常的语法“调用”符号和 lambda。根据hyperspec ,

function name n. 1. (in an environment) A symbol or a list (setf symbol) that is the name of a function in that environment. 2. A symbol or a list (setf symbol).

因此,从理论上讲,(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 一致,我会冒险猜测正确的实现应该拒绝该代码。作为第二个问题,我如何从代码片段中调用我难以置信的人为设计的无用函数,因为我在上面尝试的事情无法移植。或者,也许更有用,

最佳答案

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 表达式(尽管实现可能允许其他格式作为扩展)。

关于lisp - setf 函数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51110694/

相关文章:

lisp - 获取要在 LISP 中执行的宏

lisp - 是否有一个与Python生成器相当的lisp等效项?

amazon-s3 - sbcl vs clisp : USOCKET:TIMEOUT-ERROR. 这两个实现是否以不同方式访问 USOCKET?

lisp - 实现 forkpty() 的 GNU Common Lisp 包

common-lisp - setf函数和函数的区别

common-lisp - setf 如何在幕后工作?

c++ - 防止在C++中显示小数点前的零

lisp - 如何定义和使用 Common Lisp 包(库)?

common-lisp - 照应宏符号有一个来自不同包的前缀,我该如何摆脱它?