Created
March 19, 2018 20:47
-
-
Save miner/d4512cc1f777d46fdc2cb16fdc6f0607 to your computer and use it in GitHub Desktop.
a stateful transducer inspired by @apropos_cast episode #3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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! ())] | |
(fn | |
([] (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