为什么Clojure除了“符号”还有“关键字”?
我从其他Lisp(特别是Scheme)那里获得了一些知识。 最近我一直在阅读关于Clojure 。 我看到它有“符号”和“关键字”。 我熟悉的符号,但不包含关键字。
其他Lisp有关键字吗? 除了具有不同的符号(即:冒号)之外,关键字与符号有什么不同?
这里是关键字和符号的Clojure文档 。
关键字是评估自己的符号标识符。 他们提供非常快速的平等testing…
符号是通常用于引用其他内容的标识符。 它们可以用于程序forms来引用函数参数,让绑定,类名和全局variables…
关键字通常用作轻量级的“常量string”,例如散列图的键或multimethod的分派值。 符号通常用于命名variables和函数,除了macros等之外,它们不如直接操作为对象。 但是没有任何东西阻止你在使用关键字的地方使用符号(如果你不介意的话)。
查看差异的最简单方法是阅读Clojure源代码中的Keyword.java
和Symbol.java
。 有一些明显的实现差异。 例如,Clojure中的Symbol可以具有元数据,而关键字不能。
除了单冒号语法之外,还可以使用双冒号来创build限定名称空间的关键字。
user> :foo :foo user> ::foo :user/foo
Common Lisp也有关键字,就像Ruby和其他语言一样。 当然,这些语言略有不同。 Common Lisp关键字和Clojure关键字之间的一些区别:
-
Clojure中的关键词不是符号。
user> (symbol? :foo) false
-
关键字不属于任何名称空间,除非您具体限定它们:
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本身。