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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to