Skip to content

Instantly share code, notes, and snippets.

@cgrand
Last active August 29, 2015 14:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cgrand/5510fb70b91e69459446 to your computer and use it in GitHub Desktop.
Save cgrand/5510fb70b91e69459446 to your computer and use it in GitHub Desktop.
; discussed here https://groups.google.com/d/msg/clojure-dev/cWzMS_qqgcM/7IAhzMKzVigJ
; nested reduced
=> (transduce (comp (take 1)) conj [:a])
[:a]
=> (transduce (comp (take 1) (take 1)) conj [:a])
#<Reduced@65979031: [:a]>
=> (transduce (comp (take 1) (take 1) (take 1)) conj [:a])
#<Reduced@fcbc8d1: #<Reduced@60bea99a: [:a]>>
=> (transduce (comp (take 1) (take 1) (take 1) (take 1)) conj [:a])
#<Reduced@6e9915bb: #<Reduced@5c712302: #<Reduced@472b9f70: [:a]>>>
; problems not appearing in all contexts
; ko with transduce
=> (transduce (comp (partition-by keyword?) (take 1)) conj [] [:a])
#<Reduced@5156c42e: [[:a]]>
; but ok with sequence
=> (sequence (comp (partition-by keyword?) (take 1)) [:a])
([:a])
; well, not always
=> (sequence (comp (partition-by keyword?) (take 1) (partition-by keyword?) (take 1)) [:a])
ClassCastException clojure.lang.Reduced cannot be cast to clojure.lang.LazyTransformer clojure.lang.LazyTransformer$Stepper$1.invoke (LazyTransformer.java:104)
(defn take
"Returns a lazy sequence of the first n items in coll, or all items if
there are fewer than n. Returns a stateful transducer when
no collection is provided."
{:added "1.0"
:static true}
([n]
(fn [f1]
(let [nv (volatile! n)]
(fn
([] (f1))
([result] (f1 result))
([result input]
(let [n @nv
nn (vswap! nv dec)
result (if (pos? n)
(f1 result input)
result)]
(if (or (pos? nn) (reduced? result)) ; fix
result
(reduced result))))))))
([n coll]
(lazy-seq
(when (pos? n)
(when-let [s (seq coll)]
(cons (first s) (take (dec n) (rest s))))))))
(defn partition-by
"Applies f to each value in coll, splitting it each time f returns a
new value. Returns a lazy seq of partitions. Returns a stateful
transducer when no collection is provided."
{:added "1.2"
:static true}
([f]
(fn [f1]
(let [a (java.util.ArrayList.)
pv (volatile! ::none)]
(fn
([] (f1))
([result]
(let [result (if (.isEmpty a)
result
(let [v (vec (.toArray a))]
;;clear first!
(.clear a)
(f1 result v)))
result (if (reduced? result) @result result)] ; fix
(f1 result)))
([result input]
(let [pval @pv
val (f input)]
(vreset! pv val)
(if (or (identical? pval ::none)
(= val pval))
(do
(.add a input)
result)
(let [v (vec (.toArray a))]
(.clear a)
(let [ret (f1 result v)]
(when-not (reduced? ret)
(.add a input))
ret)))))))))
([f coll]
(lazy-seq
(when-let [s (seq coll)]
(let [fst (first s)
fv (f fst)
run (cons fst (take-while #(= fv (f %)) (next s)))]
(cons run (partition-by f (seq (drop (count run) s)))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment