Skip to content

Instantly share code, notes, and snippets.

@miner miner/apropos3.clj
Created Mar 19, 2018

What would you like to do?
a stateful transducer inspired by @apropos_cast episode #3
(defn digits [n]
{:pre [(int? n) (>= n 0)]}
(loop [digs () remainder n]
(if (< remainder 10)
(conj digs remainder)
(recur (conj digs (rem remainder 10)) (quot remainder 10)))))
(defn digits+rev [n]
(let [ds (digits n)]
(concat ds (reverse ds))))
;; based on preserving-reduced from clojure/core.clj
;; the extra level of `reduced` preserves the early termination value
(defn rf-reduce [rf result xs]
(let [rrf (fn [r x] (let [ret (rf r x)] (if (reduced? ret) (reduced ret) ret)))]
(reduce rrf result xs)))
;; They asked for a stateful transducer solution...
(defn revcat
"Returns a lazy sequence of items from coll followed by the items in reverse order. When
no collection is provided, returns a stateful transducer that buffers a reversed collection
of inputs. Each input passes through to the output. On reaching the end of input, the
buffered elements are passed in as extra inputs. Inspired by @apropos_cast episode #3."
(fn [rf]
(let [rv (volatile! ())]
([] (rf))
([result] (rf (unreduced (rf-reduce rf result @rv))))
([result input]
(vswap! rv conj input)
(rf result input))))))
([coll] (concat coll (reverse coll))))
(defn apropos3 [n]
(sequence (revcat) (digits n)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.