clojure behavior of (into {} '((:a :b) (:c :d)))


user=> (into {} '((:a :b) (:c :d)))

投掷:ClassCastException clojure.lang.Keyword cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44) .

而:

user=> (into {} (list [:a :b] [:c :d]))

很好。这是一个奇怪的区别,因为很多时候其他函数返回列表时,它们必须从向量开始:

user=> (into {} (partition 2 (interleave [:a :b] [:c :d])))

会扔,因为它partition 2 ...)导致((:a :c) (:b :d)).所以这很烦人。你基本上必须记住方法的返回类型和函数(如into)的特定行为,或者你必须让东西爆炸并在你发现它时修复它 (into {} (map vec (partition 2 (interleave [:a :b] [:c :d])))) .

into不喜欢这些对作为列表有什么具体原因吗?

原因是正如您所说,只有向量对可用于构建地图。我不知道存在此限制的实际原因。但是还有其他几种构建哈希映射的方法。如果您发现自己使用分区,也许答案是使用替代构造方法。

如果您有键和值的并行序列:

(zipmap [:a :c] [:b :d])

如果所有项目都按平面顺序排列:

(apply hash-map [:a :b :c :d])

从序列构建映射:

(into {} (for [[k v] xs]
           [k (transform v)]))

我从来没有意识到这行不通! 别忘了:

(apply hash-map (interleave [:a :b] [:c :d]))
;=> {:b :d, :a :c}

由于hash-map从标量参数隐式创建对:

(hash-map :a :c :b :d)
 ;=> {:b :d, :a :c}

你真的不需要(partition 2...)这是问题的根源。

最新更新