符号和名称是否不同?

时间:2015-03-29 19:19:36

标签: lisp elisp common-lisp symbols lexical-scope

符号和名称是否不同? Paul Graham的 On Lisp 专注于常见的口齿不清,有一些似乎暗示的讨论,例如。

  

由于lambda表达式也是函数的名称,因此它们也可以首先出现在函数调用中:
  ((lambda(x)(* x 2)3)
   6

这使得听起来像符号是名称但名称不是符号。但我不明白什么样的Lisp"对象"符号是/可能是。

这也来自尖锐引用(#')运算符v。symbol-function上的my question here。我怀疑这些不同的唯一原因是因为并非所有的名字都是符号,但我还没有足够的背景来理解这些答案(因此这个问题)。

我还要求在elisp诉普通lisp中澄清。我假设这与词汇形式有关,直到版本24(我认为24.1)才在elisp中引入。

2 个答案:

答案 0 :(得分:5)

Lambda表达式不是函数的名称。只是在Common Lisp中允许((lambda (...) ...) ...),因为它在标准中被定义为合法语法。

Common Lisp中唯一允许的函数名称是(setf symbol)等符号和列表。

例如,可以写

(defun (setf foo) (...) ...)

此处(setf foo)是函数名称。

Common Lisp中不存在其他函数名,只有符号和(setf symbol)名称。

Common Lisp Hyperspec词汇表:Function Name

  

function name n。 1.(在环境中)符号或列表(setf   symbol)这是该环境中函数的名称。 2. A   符号或列表(setf符号)。

注意:1984年的Common Lisp版本(在CLtL1中发布)只有符号作为函数名称。因此,没有定义函数名称的想法。从符号中检索函数的函数称为SYMBOL-FUNCTION。 1989年,ANSI CL标准化小组决定将setf列表添加为函数名称。它还引入了函数FDEFINITION,它类似于SYMBOL-FUNCTION,但除了符号之外还接受其他函数名称。见这里:Issue FUNCTION-NAME

答案 1 :(得分:4)

我认为Rainer's answer是正确的,但由于问题出现在对my answeranother question的评论中,我将包括(更新)我的回复来自that comment

符号是实际对象。您可以检查它,可以使用 make-symbol 等创建它们。重要的是,符号是Common Lisp中源代码的主要组件之一。函数名称,特别是在此问题出现的上下文中(函数特殊运算符的参数)是(setf symbol )<的形式的符号或列表/ strong>根据词汇表条目:

  

function name n。 1.(在环境中)符号或列表(setf符号),它是该环境中函数的名称。 2. A   符号或列表(setf符号)。

功能是一个不评估其参数的特殊运算符,因此传递符号或 setf 列表意味着:

(function car)
(function (setf car))

而不是:

(function 'car)
(function '(setf car))

现在,词汇变量,例如(let((x 42))x)中的 x ,虽然源代码中的符号表示,但实际上并不存在在运行时与符号有任何连接。 (let((x 42))x)的编译版本不需要知道关于符号 x 的任何信息。直觉上,这是有道理的,因为我们希望代码(let((y 42))y)能够编译成相同的东西。但是,当变量是特殊变量时,与符号有连接。差异最明显的是:

(let ((x 42))
  (symbol-value x))
;=> NIL

(let ((x 42))
  (declare (special x))  ; or (defparameter x ...) or (defvar x ...) earlier
  (symbol-value x))
;=> 42

我们期望词法范围的函数也是如此,例如,以下代码会导致错误,因为运行时符号 x 与本地函数之间没有连接:

(flet ((x () 42)) 
  (symbol-function 'x)) ; ERROR, no function value for symbol x

但即便如此,我们仍然可以这样做:

(flet ((x () 42))
  (function x))

这是因为功能是特殊操作符,可以访问发生的环境。这意味着(因为它很特殊,并且实现使其工作)它可以知道 x 在此定义为函数。现在可能有趣的是,由于 flet 标签被定义为采用函数名称,您可以这样做:

(flet (((setf kar) (value kons)
          ...))
  ...)