我对其他 Lisps (特别是 Scheme)有一定的了解。最近我一直在阅读关于 Clojure的文章。我看到它有“符号”和“关键字”。我熟悉的符号,但不熟悉关键字。
其他 Lisps 有关键字吗? 除了有不同的符号(例如: 冒号) ,关键字与符号有什么不同?
关键字是对它们自身进行计算的符号,所以您不必记住引用它们。
这是关键字和符号的 Clojure 文档。
关键字是自我评估的符号标识符。它们提供非常快速的相等性测试..。 符号是通常用来指代其他事物的标识符。它们可以在程序表单中用来引用函数参数、让绑定、类名和全局变量。
关键字是自我评估的符号标识符。它们提供非常快速的相等性测试..。
符号是通常用来指代其他事物的标识符。它们可以在程序表单中用来引用函数参数、让绑定、类名和全局变量。
关键字通常用作轻量级的“常量字符串”,例如用于散列映射的键或多方法的分派值。符号通常用于命名变量和函数,除了宏之类的对象外,很少直接将它们作为对象来操作。但是没有什么可以阻止你在使用关键字的任何地方使用一个符号(如果你不介意一直引用它们的话)。
查看差异的最简单方法是在 Clojure 源代码中读取 Keyword.java和 Symbol.java。在实现上有一些明显的差异。例如,Clojure 中的“符号”可以具有元数据,而“关键字”不能具有元数据。
Keyword.java
Symbol.java
除了单冒号语法之外,还可以使用双冒号创建名称空间限定的关键字。
user> :foo :foo user> ::foo :user/foo
Common Lisp 有关键字,Ruby 和其他语言也有关键字。当然,在这些语言中它们略有不同。Common Lisp 关键字和 Clojure 关键字之间的一些区别:
Clojure 中的关键字不是符号。
user> (symbol? :foo) false
Keywords don't belong to any namespace unless you specifically qualify them:
user> (namespace :foo) nil user> (namespace ::foo) "user"
(Thanks Rainer Joswig for giving me ideas of things to look at.)
Common Lisp 有 关键词符号。
关键字也是符号。
(symbolp ':foo) -> T
关键词的特殊之处:
:foo
keyword::foo
KEYWORD
keyword:foo
否则关键字是普通符号。所以关键字可以命名函数或有属性列表。
请记住: 在 Common Lisp 中,符号属于一个包: 关键字软件包:
foo
FOO
BAR
对于关键字符号,这意味着 :foo,keyword:foo和 keyword::foo都是相同的符号。因此,后两种符号通常不被使用。
所以 :foo被解析为包 KEYWORD,假设在符号名之前不给出包名意味着默认情况下 KEYWORD包。
: 关键字也被许多集合特别处理,允许一些真正方便的语法。
(:user-id (get-users-map))
和
((get-users-map) :user-id)
这会让事情变得更加灵活
对于关键字,计算哈希值并在关键字为 当查找作为散列键的关键字时,它只是 返回预计算的哈希值。对于字符串和符号,哈希值为 每次查找都会重新计算。
为什么相同的命名关键字总是相同的,它们包含自己的散列值。 由于映射和集合中的搜索是由散列键进行的,因此在大量搜索的情况下,搜索效率更高,而不是搜索本身。
关键字是全局的 ,符号是 没有。
这个示例是用 JavaScript 编写的,但我希望它能帮助我们理解这一点。
const foo = Symbol.for(":foo") // this will create a keyword const foo2 = Symbol.for(":foo") // this will return the same keyword const foo3 = Symbol(":foo") // this will create a new symbol foo === foo2 // true foo2 === foo3 // false
当您使用 Symbol函数构造一个符号时,每次都会得到一个不同的/私有的符号。当你要求通过 Symbol.for函数的符号,你会得到相同的符号,每次。
Symbol
Symbol.for
(println :foo) ; Clojure
System.out.println(RT.keyword(null, "foo")) // Java
console.log(System.for(":foo")) // JavaScript
这些都是一样的。
函数参数名称是本地的,即不是关键字。
(def foo (fn [x] (println x))) ; x is a symbol (def bar (fn [x] (println x))) ; not the same x (different symbol)