Marko Topolnik
Marko Topolnik

Reputation: 200158

Why doesn't (into {} x) accept a sequence of sequences for x

=> (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:

  1. How come (into {}) insists on vector as the container of a (key,value) pair?
  2. Why is it trying to use the 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

Answers (2)

omiel
omiel

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

Michał Marczyk
Michał Marczyk

Reputation: 84341

To answer the second question: you're passing a sequence of sequences to into. into works by repeated conjing (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 conjing it on to the map. Each such item is a sequence of two Longs. 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 Longs to Map$Entry.

Upvotes: 4

Related Questions