【问题标题】:Setf function namesSetf 函数名称
【发布时间】:2018-06-30 00:08:23
【问题描述】:

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

函数名称 n. 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 不允许我使用 sn-p 中显示的任何语法来调用它。另一方面,CLISP 将运行前两个,但在第三个仍然会出错。

我很好奇哪个编译器的行为正确。由于 SBCL 和 ABCL 同意,我会冒险猜测正确的实现应该拒绝该代码。作为第二个问题,我如何从代码 sn-p 中调用我令人难以置信的设计无用的函数,因为我上面尝试的东西不能移植。或者,也许更有用的是,

【问题讨论】:

标签: lisp common-lisp setf


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-10
    • 2013-12-03
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 2021-10-31
    • 2020-08-22
    相关资源
    最近更新 更多