Welcome! Please see the About page for a little more info on how this works.

0 votes
in Collections by
closed ago by


Because PHMs implement clojure.lang.IKVReduce and IPersistentMap, they have nondeterministic dispatch through the protocol that backs reduce-kv (clojure.core.protocols/IKVReduce).

A potential way to solve this is to add an instance check for clojure.lang.IKVReduce inside reduce-kv (This is similar to how reduce checks for IReduceInit)

Another approach is to extend the protocol to PersistentHashMap and PersistentArrayMap directly (in addition to preserving the existing extensions)

closed with the note: Fixed in 1.11.0-alpha2

3 Answers

0 votes

Comment made by: bronsa

CLJ-1807 offers a generic solution for this class of problems

0 votes
_Comment made by: gshayban_

Repro code

(def C (atom 0))

;; reextend for instrumentation
(extend-protocol clojure.core.protocols/IKVReduce
 ;;slow path default
   [amap f init]
   (swap! C inc)
   (reduce (fn [ret [k v]] (f ret k v)) init amap)))

(reduce-kv (fn [_ _ _]) nil (array-map 1 2 3 4))
(println "slowpaths" @C)
(reduce-kv (fn [_ _ _]) nil (hash-map 1 2 3 4))
(println "slowpaths" @C)

Repro output

➜  dev /usr/lib/jvm/java-8-openjdk/bin/java -cp $(clojure -Spath) clojure.main kvfastpath.clj
slowpaths 1
slowpaths 2
➜  dev /usr/lib/jvm/java-11-openjdk/bin/java -cp $(clojure -Spath) clojure.main kvfastpath.clj
slowpaths 0
slowpaths 0
0 votes
Reference: https://clojure.atlassian.net/browse/CLJ-1879 (reported by gshayban)