为什么使用关键字或符号作为函数来查找地图中的值有效?

时间:2011-08-02 16:43:46

标签: clojure

引自 Clojure的喜悦,第4.3.1节 -

  

因为关键字是自我评估并提供快速相等性检查,所以它们几乎总是在地图键的上下文中使用。使用关键字作为映射键的一个同样重要的原因是它们可以用作函数,将映射作为参数,以执行值查找:

(def population {:zombies 2700, :humans 9})
(:zombies population)
;=> 2700
(println (/ (:zombies population)
(:humans population))
"zombies per capita")
; 300 zombies per capita

我不清楚这里发生了什么。某种程度上(:zombies population)必须转变为(get population :zombies),对吧?这究竟是如何工作的?关键字评估自身,而不是函数。读者是否注意列表中的第一件事是关键字的情况,并添加get并将关键字移动到列表的末尾?

3 个答案:

答案 0 :(得分:24)

来自official documentation的引文:

  

关键字为一个参数(一个映射)的invoke()实现IFn,并带有可选的第二个参数(默认值)。例如(:mykey my-hash-map:none)表示与(get my-hash-map:mykey:none)相同。见get。

Clojure可以将关键字作为函数调用,因为它实现了与函数相同的接口。符号也一样......

答案 1 :(得分:18)

关键字各种功能。没有读者魔法,因为你会看到你是否尝试(let [m {:humans 100}, k :humans] (k m))。我希望你会同意读者无法把它变成一个get(编译器可以,但你可以假装我已经使k的值取决于编译器不能的if表达式预测,例如用户输入)。

因为Clojure的核心数据类型是接口,而Java对象可以实现许多接口,所以一段数据可以有多种类型。它是关键字吗?是。这是一个功能吗?也是:

user> (keyword? :k)
true
user> (ifn? :k)
true
user> (.invoke :k {:k 1})
1

答案 2 :(得分:6)

关键字实施IFn,

https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Keyword.java

并且其invoke方法处理调用get。