Hi all,

I am currently testing performance of different reduce and map implementations
in my programs and have problems because their treatment of nil is different.
The "normal" clojure.core implementations of reduce and map work well when
called on nil, but reduce-kv and functions in clojure.reducers throw
exceptions.

--- snip ---
user=> (defn fold-into-vec
  "Provided a reducer, concatenate into a vector.

  Note: same as (into [] coll), but parallel."
  ([coll]
   (r/fold (r/monoid into vector) conj coll))
  ([n coll]
   (r/fold n (r/monoid into vector) conj coll)))

user=> (map (fn [el] (* 2 el)) nil)
()
user=> (mapv (fn [el] (* 2 el)) nil)
[]
user=> (fold-into-vec (r/map (fn [el] (* 2 el)) nil))
#<IllegalArgumentException java.lang.IllegalArgumentException: No 
implementation of method: :coll-fold of protocol: 
#'clojure.core.reducers/CollFold found for class: nil>
user=> (reduce (fn [ret el] (+ el el)) {} nil)
{}
user=> (reduce (fn [ret [k v]] (+ k v)) {} nil)
{}
user=> (reduce-kv (fn [ret k v] (+ k v)) {} nil)
#<IllegalArgumentException java.lang.IllegalArgumentException: No 
implementation of method: :kv-reduce of protocol: 
#'clojure.core.protocols/IKVReduce found for class: nil>
--- snip ---

I find this behaviour quite unfortunate because I now have to explicitly test
for nil? and ensure consistent behaviour. This inconsistency violates the
principle of least-surprise and I am not sure if the current behaviour is
intentional or merely an unfortunate implementation detail.

Wouldn't it make sense if reduce-kv and r/map mirror the behaviour of reduce,
map and mapv in core?

P.S. Would it be possible to have something like fold-into-vec in 
clojure.reducers?
-- 
Wolodja <babi...@gmail.com>

4096R/CAF14EFC
081C B7CD FF04 2BA9 94EA  36B2 8B7F 7D30 CAF1 4EFC

Attachment: signature.asc
Description: Digital signature

Reply via email to