Hi all,
I've had a case where reduce with merging operations throws errors on lazy
sequences. I thought I should check in for insight before logging a bug.
Maybe using maps as keys has something to do with it. too (I've since
refactored)
(reduce merge-student-demand everybody)
Throws:
IllegalArgumentException contains? not supported on type:clojure.lang.LazySeq
clojure.lang.RT.contains (RT.java:814)
However:
(reduce merge-student-demand (take 5 everybody))
works just fine.
As does:
(merge-student-demand {} (first everybody))
None of my code uses contains? directly, neither does reduce, so I figure
it must be one of the invocations of merge-with in my code.
Here are the relevant chunks of code:
;; I can see how this would produce a LazySeq of hash-maps
(defn prioritized-courses [needed-courses]
(->
(for [course-set needed-courses
:let [demand (course-demand course-set)]]
(map #(assoc % :demand demand) (:courses course-set)))
flatten))
;; There are two merge-with instances here. This one is used inside the
next one.
(defn merge-demand [acc m]
;; I was admittedly doing something corny here, using a map as a key.
(merge-with + acc {{:prefix (:prefix m) :number (:number m)} (:demand
m)})) ;; Sum demand by course
;; Merging again here:
(defn merge-student-demand [acc student]
(merge-with merge-demand acc {(:id student) (prioritized-courses
(:needed-courses student))}))
(reduce merge-student-demand everybody)
=> IllegalArgumentException contains? not supported on
type:clojure.lang.LazySeq
clojure.lang.RT.contains (RT.java:814)
I figure it's likely the Clojure core (1.8.0) merge-with function, being
the first instance of contains? I could find:
text-mining.core=> (source merge-with)
(defn merge-with
"Returns a map that consists of the rest of the maps conj-ed onto
the first. If a key occurs in more than one map, the mapping(s)
from the latter (left-to-right) will be combined with the mapping in
the result by calling (f val-in-result val-in-latter)."
{:added "1.0"
:static true}
[f & maps]
(when (some identity maps)
(let [merge-entry (fn [m e]
(let [k (key e) v (val e)]
(if (contains? m k) ;; contains? invoked here
(assoc m k (f (get m k) v))
(assoc m k v))))
merge2 (fn [m1 m2]
(reduce1 merge-entry (or m1 {}) (seq m2)))]
(reduce1 merge2 maps))))
Well that's my mystery. I should get around to fiddling and seeing if I
can reproduce this with a more straighforward program.
Best,
Nathan
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.