在Clojure中,为什么`into`地图(`(into{},,,)`)适用于`vectors`而不适用于`lists`?

我可以用向量列表构建地图:

user=> (into {} (list (vector "a" "b") (vector "c" "d")))
{"a" "b", "c" "d"}

但是,如果我尝试使用列表列表来执行此操作,则会失败:

user=> (into {} (list (list "a" "b") (list "c" "d")))
Execution error (ClassCastException) at user/eval3 (REPL:1).
class java.lang.String cannot be cast to class java.util.Map$Entry (java.lang.String and java.util.Map$Entry are in module java.base of loader 'bootstrap')

为什么?

回答

当你这样做时,(into {} coll)它相当于(reduce conj {} coll)所以你的每个元素都coll被用作第二个参数,conj以散列映射作为第一个参数。

conj内置clojure.lang.RT并调用(在这种情况下)APersistentMap.cons()添加这里的元素:https : //github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/APersistentMap.java#L24

从中可以看出,如果参数是 a MapEntry,它将作为键/值对添加到哈希映射中:(seq my-hash-map)生成一个MapEntry项目序列。

如果参数是一个具有两个元素的向量,它将作为键/值对添加,其中键是该向量的第一个元素,值是该向量的第二个元素。

否则,它会尝试将参数转换为序列,然后将每个元素强制转换MapEntry为键/值对并将其添加为键/值对

当您传递向量列表(双元素向量)时,它们会根据上述第二种情况作为键/值对添加。当您传递列表列表时,会调用第三种情况,它会尝试将内部列表的每个元素强制转换为 a MapEntry-- 失败,因为这些元素是String's。


以上是在Clojure中,为什么`into`地图(`(into{},,,)`)适用于`vectors`而不适用于`lists`?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>