为什么Clojure除了“符号”还有“关键字”?

我从其他Lisp(特别是Scheme)那里获得了一些知识。 最近我一直在阅读关于Clojure 。 我看到它有“符号”和“关键字”。 我熟悉的符号,但不包含关键字。

其他Lisp有关键字吗? 除了具有不同的符号(即:冒号)之外,关键字与符号有什么不同?

这里是关键字和符号的Clojure文档 。

关键字是评估自己的符号标识符。 他们提供非常快速的平等testing…

符号是通常用于引用其他内容的标识符。 它们可以用于程序forms来引用函数参数,让绑定,类名和全局variables…

关键字通常用作轻量级的“常量string”,例如散列图的键或multimethod的分派值。 符号通常用于命名variables和函数,除了macros等之外,它们不如直接操作为对象。 但是没有任何东西阻止你在使用关键字的地方使用符号(如果你不介意的话)。

查看差异的最简单方法是阅读Clojure源代码中的Keyword.javaSymbol.java 。 有一些明显的实现差异。 例如,Clojure中的Symbol可以具有元数据,而关键字不能。

除了单冒号语法之外,还可以使用双冒号来创build限定名称空间的关键字。

 user> :foo :foo user> ::foo :user/foo 

Common Lisp也有关键字,就像Ruby和其他语言一样。 当然,这些语言略有不同。 Common Lisp关键字和Clojure关键字之间的一些区别:

  1. Clojure中的关键词不是符号。

     user> (symbol? :foo) false 
  2. 关键字不属于任何名称空间,除非您具体限定它们:

     user> (namespace :foo) nil user> (namespace ::foo) "user" 

(感谢Rainer Joswig为我提供了一些想法。

Common Lisp有关键字符号。

关键字也是符号。

 (symbolp ':foo) -> T 

什么使关键字特别:

  • :foo被Common Lisp阅读器parsing为符号关键字:: foo
  • 关键字评估自己::foo – >:foo
  • 关键字符号的home包是KEYWORD包:关键字:foo – >:foo
  • 关键字从KEYWORD包中导出
  • 关键字是常量,不允许分配不同的值

否则关键字是普通符号。 所以关键字可以命名函数或具有属性列表。

记住:Common Lisp符号属于一个包。 这可以写成:

  • foo,当前包中可以访问该符号
  • foo:bar,当符号FOO从包BAR中导出时
  • foo :: bar,当符号FOO在包BAR中时

对于关键字符号,这意味着:foo,关键字:foo和关键字:: foo都是相同的符号。 因此后两个符号通常不被使用。

所以:foo只是被parsing到KEYWORD包中,假设在符号名前没有给出包名,这意味着默认情况下是KEYWORD包。

关键词是评估自己的符号,所以你不必记得引用它们。

:关键字也被许多集合特别对待,允许一些非常方便的语法。

 (:user-id (get-users-map)) 

是相同的

 ((get-users-map) :user-id) 

这使事情变得更灵活一点

对于关键字,首次构build关键字时计算和caching哈希值。 查找关键字作为散列键时,它只是返回预先计算的散列值。 对于string和符号,每次查找时都会重新计算散列值。

为什么相同的命名关键字总是相同的,它们包含自己的哈希值。 由于search地图和集合是由散列键组成的,所以在search的情况下search效率更高,而不是search本身。