Clojure:使用哈希作为函数好吗?

时间:2015-09-25 05:08:15

标签: clojure hashmap

这两种方法都有效:

=> (def hash {:a "potato" :b "pants"})
#'hash
=> (hash :a)
"potato"
=> (:a hash)
"potato"

我是否应该选择其中一种而不是另一种?我看到更多人在做后者(:a hash) ...为什么?我喜欢前(hash :a),因为它类似于(-> hash :a :b :c)的结构,我更喜欢吵闹的(get-in hash [:a :b :c])

它们之间是否存在效率差异?

2 个答案:

答案 0 :(得分:3)

拥有静态关键字密钥和动态地图时使用(:key hash)。 拥有静态地图和动态密钥时,请使用({:a 1 :b 2} k)。 map和key都是动态的,请使用(get hash key)。这说明了为什么

> (def hm nil)
> (def knil nil)
> (def kother 1)

> (hm :key)
NullPointerException ...
> (:key hm)
nil

> (kother {:a 1})
ClassCastException
> (knil {:a 1})
NullPointerException
> ({:a 1} kother)
nil

> (get hm knil)
nil
> (get hm kother)
nil

或者你可以在任何地方使用get并且不要为此烦恼。但是输入的时间更长,代码可能会因括号而变得混乱。如果您确定(hm key)不是cipher

,使用nil看起来合理
> (def message "hello")
> (let [cipher {\h \1 \e \f \l \# \o \p}]  
    (apply str (map cipher message)))
"1f##p"

答案 1 :(得分:1)

@leeor给出的链接非常全面。我在这里再添加一些实验:

user> (time (let [m {:a :b}] (dotimes [i 900000000] (m :a))))
"Elapsed time: 4609.565862 msecs"
=> nil
user> (time (let [m {:a :b}] (dotimes [i 900000000] (get m :a))))
"Elapsed time: 9556.065868 msecs"
=> nil
user> (time (let [m {:a :b}] (dotimes [i 900000000] (:a m))))
"Elapsed time: 11220.804791 msecs"
=> nil

这种结果与@ amalloy关于热点优化的论点相矛盾。也许是因为REPL解释不是热点优化的?