从这个问题的后续行动:使用Clojure的Idiomatic clojure map lookup by keyword什么优势有没有使用“得到”,而不是访问一个地图
地图的访问可以通过多种方式来完成。
(def m {:a 1}
(get m :a) ;; => 1
(:a m) ;; => 1
(m :a) ;; => 1
我知道我主要使用第二种形式,有时第三种,很少是第一种。各自使用的优点(速度/组合性)有哪些?
从这个问题的后续行动:使用Clojure的Idiomatic clojure map lookup by keyword什么优势有没有使用“得到”,而不是访问一个地图
地图的访问可以通过多种方式来完成。
(def m {:a 1}
(get m :a) ;; => 1
(:a m) ;; => 1
(m :a) ;; => 1
我知道我主要使用第二种形式,有时第三种,很少是第一种。各自使用的优点(速度/组合性)有哪些?
从the clojure web page我们看到
地图实现IFN一个说法,为的invoke()(一键很多)与 可选的第二个参数(默认值),即地图是其功能 其键。零键和值都可以。
有时在Clojure的引擎盖下看看是有好处的。如果你看看什么invoke
看起来像一张地图,你看到这个:
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java#L196
它显然调用地图的valAt
方法。
如果你看看什么get
功能时,与地图叫呢,这是clojure.lang.RT.get
一个电话,这真的归结到同一个呼叫valAt
的地图(地图实现ILookUp因为他们是Associatives):
https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/RT.java#L634。
对于使用键和未找到值调用的映射也是如此。那么,有什么优势?既然两种方式都差不多,性能方面我什么都不会说。这只是语法上的便利。
我不认为存在速度差异,即使情况如此,这将是一个实施细节。
就我个人而言,我更喜欢第二个选项(:a m),因为它有时会让代码变得更容易。例如,我经常通过地图的序列迭代:
(def foo '({:a 1} {:a 2} {:a 3}))
如果我要筛选的所有值:一个我现在可以使用:
(map :a foo)
而不是
(map #(get % :a) foo)
或
(map #(% :a) foo)
中当然,这是个人品味的问题。
您可以通过get
到partial
等建立HOFs与您的数据搞乱,虽然它不经常出现。
user=> (def data {"a" 1 :b 2})
#'user/data
user=> (map (partial get data) (keys data))
(1 2)
我用第三种形式当数据字符串作为键
这并没有真正解决这个问题。你可以像'(地图数据(键数据))'一样容易地获得'(vals data)'的等价物。 – amalloy
问题的关键在于get可以在函数转换函数中组合,以在数据映射可用之前生成数据转换函数。这个例子说明了这一点,尽管实际上它与其他特定于问题的约束结合在一起。 –
get
是有用的,当在地图可能是零或不一个地图,关键可能是一些不可赎回(即不是关键字)
(def m nil)
(def k "some-key")
(m k) => NullPointerException
(k m) => ClassCastException java.lang.String cannot be cast to clojure.lang.IFn
(get m k) => nil
(get m :foo :default) => :default
要添加到列表中,得到的是也有用使用线程宏观->
,你需要通过一个按键是不是关键字
(let [m {"a" :a}] (-> m (get "a")))
使用关键字第一种方法是在访问与价值的最简洁的方式
一个优点访问时在地图为零的情况下的宽容行为。
查看您链接问题中的答案。想到的唯一另外一件事就是获得3-arity版本(get map key not found),你在哪里得到(双关语)来指定默认值。 –
@ A.Webb你可以为所有三种用途指定一个默认值:'(:k m默认值)'和'(m:k默认值)'都可以,只要m不是零。 – amalloy
@amalloy啊,很酷,谢谢你指出了! –