Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Wrapping reducer vs reducer with atom
(ns redtest.core
(:require [clojure.core.reducers]
[clojure.core.protocols :refer
[CollReduce coll-reduce]]))
;; state is kept in a ret
(deftype WrapState [ret n])
(deftype WrapTake [coll n]
CollReduce
(coll-reduce [this f init]
(let [init-state (->WrapState init n)
tf (fn [^WrapState state val]
(let [ret (.-ret state)
ni (dec (.-n state))
nret (f ret val)]
(cond (reduced? nret)
(reduced (->WrapState @nret nil))
(zero? ni)
(reduced (->WrapState nret nil))
:else (->WrapState nret ni))))
ret-state (coll-reduce coll tf init-state)]
(.-ret ^WrapState ret-state))))
(def wrap-take (->WrapTake [1 2 3 4 5 6] 3))
(time
(dotimes [x 100000]
(reduce conj [] wrap-take)))
;; state is kept in atom
(deftype AtomTake [coll n]
CollReduce
(coll-reduce [this f init]
(let [na (atom n)
tf (fn [ret val]
(swap! na dec)
(let [ni @na
nret (f ret val)]
(if (zero? ni)
(reduced nret)
nret)))]
(coll-reduce coll tf init))))
(def atom-take (->AtomTake [1 2 3 4 5 6] 3))
(time
(dotimes [x 100000]
(reduce conj [] atom-take)))
;; state is kept in volatile
(deftype VolatileTake [coll n]
CollReduce
(coll-reduce [this f init]
(let [na (volatile! n)
tf (fn [ret val]
(vswap! na dec)
(let [ni @na
nret (f ret val)]
(if (zero? ni)
(reduced nret)
nret)))]
(coll-reduce coll tf init))))
(def volatile-take (->VolatileTake [1 2 3 4 5 6] 3))
(time
(dotimes [x 100000]
(reduce conj [] volatile-take)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment