Syntax 为什么在公共Lisp中冒号位于变量之前

Syntax 为什么在公共Lisp中冒号位于变量之前,syntax,common-lisp,colon,Syntax,Common Lisp,Colon,Common Lisp中前面变量的冒号表示什么意思?我见过这样的程序,我将在这里介绍一些示例代码,其中包含大量函数 (defun expand (successorf node) (mapcar (lambda (action-state-cost) (let ((action (car action-state-cost)) (state (cadr action-state-cost)) (cost

Common Lisp中前面变量的冒号表示什么意思?我见过这样的程序,我将在这里介绍一些示例代码,其中包含大量函数

(defun expand (successorf node)
    (mapcar (lambda (action-state-cost)
          (let ((action (car action-state-cost))
                (state (cadr action-state-cost))
                (cost (caddr action-state-cost)))
            (make-node :state state :parent node
                       :action action :path-cost (+ (node-path-cost node) cost)
                       :depth (1+ (node-depth node)))
            ))
      (funcall successorf (node-state node))
      ))

实际上,它们不是变量;这些是关键词。它们是一种特殊的有效标记,类似于其他语言中的“原子”。这是一种方便的内置方式,可以将命名(几乎总是可选)参数传递到函数调用中


描述函数调用的语法。

关键字符号

:foo
是一个符号

  • 关键字
    包中实习并从中导出
  • 不断地自我约束
用法

当需要以下属性的组合时,将使用关键字符号:

  • 符号是正确的数据结构
  • 具有相同名称的符号应该是唯一的(通过将它们插入包中)->package
    关键字
  • 不需要或不需要不同的软件包->软件包
    关键字
  • 编写符号应该很容易,因为不需要引用它们-->
    :foo
    ':foo
  • 不需要充当具有不同值的变量的能力->
    :foo
    计算结果为
    :foo
    本身,仅计算结果为
    :foo
在公共Lisp中,符号通常可以在包中(一种名称空间)

foo
中未报告的符号
bar
写为
foo::bar
。双冒号位于包名称和符号名称之间

然后,导出的符号被写为
foo:bar
。使用单个冒号

如果符号在当前软件包中可用,则在没有软件包的情况下写入为
bar

软件包
关键字

有一个名为
关键字
的特殊包。该软件包中的符号
bar
简单且始终写为
:bar

示例

这些关键字符号还具有以下有趣的属性:这些符号是从包中自动导出的
关键字
(因此
关键字::bar
关键字:bar
::bar
:bar
都是相同的符号),它们对自身进行评估:

CL-USER 5 > :bar
:BAR

CL-USER 6 > (describe :bar)

:BAR is a SYMBOL
NAME          "BAR"
VALUE         :BAR
FUNCTION      #<unbound function>
PLIST         NIL
PACKAGE       #<The KEYWORD package, 0/4 internal, 5830/8192 external>

CL-USER 7 > (eq 'keyword::bar ':bar)
T

CL-USER 8 > (eq :bar ':bar)  ; quoted or unquoted, each subform evaluates to :bar
T
通常,它们也用于实例和结构构造的参数中

(defstruct node state parent action)
DEFSTRUCT
是一个常见的Lisp宏,它生成多个函数。其中一个是函数
MAKE-NODE
,可以用作:

(make-node :state 'open
           :parent some-parent
           :action an-action)
注意:有时数据也可能是关键字。例如,在上面的表单中,状态可能是
:open
,而不是
open

(make-node :state :open
           :parent some-parent
           :action an-action)

您可以这样写:“导出的符号…写为
foo:bar
。使用单个冒号…”以及“自动导出[keyword]符号”,但您的示例显示
(eq'keyword::bar':bar)
。如果总是导出关键字,为什么要使用双冒号?
可以与导出和非导出符号一起使用吗?@GlennSlayden是的,每个内部符号,无论导出还是未导出,都可以写为package::name。只有导出的符号才能写入package:name。只有关键字符号可以写为:name。为了完整起见,关于
::bar
?它仍然是指
关键字
包,还是现在是其他形式的全局搜索?很抱歉成为一个口齿不清的新手。@GlennSlayden::bar,::bar,keyword:bar,keyword::bar都是相同的符号。(mapcar(lambda(sym)(等式sym:bar))”(:bar::bar关键字:bar关键字::bar))->(T)
(make-node :state :open
           :parent some-parent
           :action an-action)