Clojure 使用'有什么好处;获取';而是访问地图

Clojure 使用'有什么好处;获取';而是访问地图,clojure,Clojure,就这一问题采取后续行动: 使用clojure进行地图访问有多种方式 (def m {:a 1} (get m :a) ;; => 1 (:a m) ;; => 1 (m :a) ;; => 1 我知道我主要使用第二种形式,有时使用第三种形式,很少使用第一种形式。使用每种方法的优点(速度/可组合性)是什么?我不认为存在速度差异,即使是这样,这也是一个实现细节 就我个人而言,我更喜欢第二个选项(:am),因为它有时会让代码看起来更简单。例如,我经常需要遍历一系列贴图: (def

就这一问题采取后续行动:

使用clojure进行地图访问有多种方式

(def m {:a 1}

(get m :a) ;; => 1
(:a m) ;; => 1
(m :a) ;; => 1

我知道我主要使用第二种形式,有时使用第三种形式,很少使用第一种形式。使用每种方法的优点(速度/可组合性)是什么?

我不认为存在速度差异,即使是这样,这也是一个实现细节

就我个人而言,我更喜欢第二个选项(:am),因为它有时会让代码看起来更简单。例如,我经常需要遍历一系列贴图:

(def foo '({:a 1} {:a 2} {:a 3}))
如果我想过滤:a的所有值,我现在可以使用:

(map :a foo)
而不是

(map #(get % :a) foo)


当然,这是个人喜好的问题。

你可以将
get
传递到
partial
等,以建立HOF,从而干扰你的数据,尽管它并不经常出现

user=> (def data {"a" 1 :b 2})
#'user/data
user=> (map (partial get data) (keys data))
(1 2)
当数据中有字符串作为键时,我经常使用第三种形式

映射实现IFn,用于带有 可选的第二个参数(默认值),即映射是 他们的钥匙。nil键和值都可以

有时,在Clojure的兜帽下看一看是值得的。如果在地图中查找
invoke
的外观,您会看到:

它显然调用了map的
valAt
方法

如果您查看
get
函数在使用map调用时的功能,这是对
clojure.lang.RT.get
的调用,这实际上归结为对map的
valAt
的相同调用(map实现ILookUp,因为它们是:


对于使用键和未找到值调用的映射也是如此。那么,优势是什么?由于这两种方法归结起来几乎相同,所以在性能方面我什么也不说。这只是语法上的方便

get
在map可以是nil或not-a-map,并且键可以是不可调用的东西(即不是关键字)时非常有用


要添加到列表中,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

(设[m{“a”:a}]
(->m
(得到“a”))

使用关键字优先法的一个优点是,在地图为零的情况下,它是以宽容的行为访问值的最简洁的方法。

请参阅您链接的问题中的答案。get唯一想到的另一件事是3-arity版本(找不到get映射键),在该版本中,您可以指定默认值。@a.Webb您可以为所有三种用途指定默认值:
(:k m default)
(m:k default)
,只要m当然不是零。@amalloy啊,酷,谢谢你指出这一点!这并不能真正解决问题。您可以同样轻松地
(映射数据(键数据))
获得与
(VAL数据)
等价的数据。要点是,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