Guys, I've found myself needing a function that I am sure cannot be an original but I'm not aware of it existing anywhere...
It is a cross between 'map', 'reduce' and 'iterate'... Given a function 'f' and a sequence 's' it would return you a sequence of : ``` [(f s[0]) (f (f s[0]) s[1]) (f (f (f s[0]) s[1]) s[2]) ...] ``` or, more concretely, e.g.: ``` util-test> (stateful-map + [0 1 2 3 4 5]) [0 1 3 6 10 15] util-test> ``` I have a couple of approaches to it - one using reduce: ``` (defn stateful-map-1 [f [h & t]] (reduce (fn [acc v] (conj acc (f (last acc) v))) [h] t)) ``` and another, mapping using a stateful function: ``` (let [secret (Object.)] (defn stateful-mapper [f] (let [state (volatile! secret)] (fn [v] (vswap! state (fn [old new] (if (= secret old) (f new) (f old new))) v))))) (defn stateful-map-2 [f s] (mapv (stateful-mapper f) s)) ``` The former feels more idiomatic whereas the latter (although uglier) is more efficient and has the added benefit of being able to be used for general map-ing which is important as I want to use this approach to transduce a clojure.async.channel. It could, of course, be expressed directly as a transducer but it feels like something simpler that should only be lifted to a transducer as and when needed (see test below) ... Here is my working testsuite: ``` (deftest stateful-map-test (testing "reduction" (is (= [0 1 3 6 10 15] (stateful-map-1 + [0 1 2 3 4 5])))) (testing "mapping stateful function" (is (= [0 1 3 6 10 15] (stateful-map-2 + [0 1 2 3 4 5])))) (testing "transduction" (is (= [0 1 3 6 10 15] (sequence (map (stateful-mapper +)) [0 1 2 3 4 5]))))) ``` Am I missing a standard way of doing this in Clojure ? Or is a stateful function the best answer ? Interested in your thoughts, Jules -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/clojure/f1ada73f-8249-431a-9f4d-580aea12bdefn%40googlegroups.com.