这两种方法都有效:
=> (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])
。
它们之间是否存在效率差异?
答案 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解释不是热点优化的?