Reputation: 200158
=> (into {} (for [x [["1" "2"] ["3" "4"]]] (map #(Long/parseLong %) x)))
ClassCastException java.lang.Long cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44)
=> (into {} (for [x [["1" "2"] ["3" "4"]]] (seq (map #(Long/parseLong %) x))))
ClassCastException java.lang.Long cannot be cast to java.util.Map$Entry clojure.lang.ATransientMap.conj (ATransientMap.java:44)
=> (into {} (for [x [["1" "2"] ["3" "4"]]] (vec (map #(Long/parseLong %) x))))
{1 2, 3 4}
I've got two related questions:
(into {})
insists on vector as the container of a (key,value) pair?Long
, which is the constituent of the pair, as the pair itself? Shouldn't it at least complain about seeing a non-vector, regardless of what it contains?BTW testing with Clojure 1.5.1.
Upvotes: 1
Views: 284
Reputation: 1593
into
is implemented on top of conj
.
(into {} ...) ;; equivalent to (below)
(-> {}
(conj (map #(Long/parseLong %) ["1" "2"]) ;; produces the same exception
(conj (map #(Long/parseLong %) ["3" "4"]))
conj
expects either a map, a map entry or a two-element vector. Consider this excerpt from http://clojure.org/data_structures#toc17:
conj expects another (possibly single entry) map as the item, and returns a new map which is the old map plus the entries from the new, which may overwrite entries of the old. conj also accepts a MapEntry or a vector of two items (key and value).
Upvotes: 4
Reputation: 84341
To answer the second question: you're passing a sequence of sequences to into
. into
works by repeated conj
ing (or conj!
ing, if possible; the result is equivalent). Here at each step you'll be taking one item from your sequence of sequences and conj
ing it on to the map. Each such item is a sequence of two Long
s. When you conj
a sequence on to a map, conj
assumes that it is a sequence of map entries and casts each element to Map$Entry
.
So, here it'll be attempting to cast your Long
s to Map$Entry
.
Upvotes: 4