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

Nat*_*hes 21 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
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*Ott 24

官方文件引用:

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

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

  • @KingCode 如果它不是`ILookup`、java`Map` 或`IPersistentSet`,那么`RT` 中的`getFrom` 只会返回`null`,在这种情况下`Keyword` 中的`invoke` 方法只是简单的在您的示例中返回 `notFound` 值或 `:baz`。 (2认同)

ama*_*loy 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
Run Code Online (Sandbox Code Playgroud)


Ham*_*aya 6

关键词实现IFn,

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

并且它的invoke方法处理调用get.