代码之家  ›  专栏  ›  技术社区  ›  Silvio Mayolo

setf函数名

  •  0
  • Silvio Mayolo  · 技术社区  · 6 年前

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

    函数名 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都同意,我就冒险猜测正确的实现应该拒绝该代码。作为第二个问题,我如何从代码片段中调用我的设计得难以置信的无用函数,因为我在上面尝试的东西不能移植。或者,也许更有用的是,

    1 回复  |  直到 6 年前
        1
  •  6
  •   Barmar Mark Tolonen    6 年前

    一个 SETF 函数必须至少接受一个参数,这是要存储在该位置的新值。它还可以包含其他参数,这些参数将从调用 SETF公司 是的。

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