Dan, I haven't read yours or Christophe Grand's articles thoroughly enough even to know whether your ideas are similar, but you may be interested to read this thread, and the blog posts written by Christophe, linked from his first message in this discussion thread: https://groups.google.com/forum/#!topic/clojure-dev/cWzMS_qqgcM
On Wed, Oct 15, 2014 at 6:22 AM, Daniel James <dwhja...@gmail.com> wrote: > Hi All, > > I’d like to offer an alternative implementation of clojure.core/transduce. > > (I’ve done some searching, and I didn’t find any evidence that this has > been raised before, but my apologies if I missed anything.) > > This alternative is best motivated by example. Consider the following > transducers: > > (defn init-with > [x] > (fn [rf] > (fn > ([] (rf (rf) x)) > ([result] (rf result)) > ([result input] > (rf result input))))) > > (defn complete-with > [x] > (fn [rf] > (fn > ([] (rf)) > ([result] > (rf (rf result x))) > ([result input] > (rf result input))))) > > (defn dupl > [] > (fn [rf] > (fn > ([] (rf)) > ([result] (rf result)) > ([result input] > (rf (rf result input) > input))))) > > I have selected these as each illustrate something ‘interesting’ occurring > in each of the three arities of the reducing functions produced. > > Now consider the following transducer, which transforms numeric reducing > functions. > > (def xform (comp > (map inc) > (complete-with 10) > (map inc) > (init-with 100) > (map inc) > (dupl))) > > The current behavior of transduce (and into, for illustration purposes) is: > > (into [37] xform (range 5)) > ;=> [37 3 3 4 4 5 5 6 6 7 7 12 12] > > > (transduce xform + 37 (range 5)) > ;=> 111 > > (reduce + (into [37] xform (range 5))) > ;=> 111 > > (transduce xform + (range 5)) > ;=> 74 > > > So the dupl and complete-with transducers work as I expected, but the > init-with does not. > > What I was hoping for was: > > ;=> [37 101 101 3 3 4 4 5 5 6 6 7 7 12 12] > > ;=> 313 > > ;=> 313 > > ;=> 276 > > > This is because transduce and into are currently implemented as something > equivalent to the following: > > (defn curr-transduce > ([xform f coll] > (transduce xform f (f) coll)) > ([xform f init coll] > (let [rf (xform f)] > (rf (reduce rf init coll))))) > > > (defn curr-into > [to xform from] > (curr-transduce xform conj to from)) > > In the first arity of transduce, the initial value is taken from the > reducing function f, not the reducing function produced by (xform f). > And in the second arity, the supplied initial value is supplied directly > to the reduction. > These both bypass the transducer xform entirely, so the zeroth-arity is > never invoked and no transformation occurs. > > I would like to propose the following alternative implementation: > > (defn alt-transduce > ([xform f coll] > (let [rf (xform f)] > (rf (reduce rf (rf) coll)))) > ([xform f init coll] > (let [rf (xform > (fn > ([] init) > ([result] (f result)) > ([result input] (f result input))))] > (rf (reduce rf (rf) coll))))) > > In the first arity, the initial value is drawn from the transformed > reducing function, rather than the supplied reducing function. > In the second arity, a reducing function is constructed from f and init to > be f in arity 1 and 2, but return init in arity 0. > Both cases ensure that the transducer is used to transform all three > components of the reduction: init, step, and completion. > > Because of the way that the second arity is implemented, into doesn’t need > to change: > > (defn alt-into > [to xform from] > (alt-transduce xform conj to from)) > > The effect is that the reducing function passed to xform is conj, except > in arity 0, where the `to` collection is returned. > > These return the results I was originally expecting: > > (alt-into [37] xform (range 5)) > ;=> [37 101 101 3 3 4 4 5 5 6 6 7 7 12 12] > > (reduce + (alt-into [37] xform (range 5))) > ;=> 313 > > (alt-transduce xform + 37 (range 5)) > ;=> 313 > > (alt-transduce xform + (range 5)) > ;=> 276 > > > I went though the list of transducers currently provided in clojure.core > and none of them do anything ‘interesting’ in zeroth-arity init component, > so the alternate implementation would not change their observable behavior. > This only affects transducers that do something other than the trivial > implementation of the zero-arity. The discussion > https://groups.google.com/d/topic/clojure/M-13lRPfguc/discussion was the > only related one I could find. > > Thanks, > Dan > > -- > 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. > For more options, visit https://groups.google.com/d/optout. > -- 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. For more options, visit https://groups.google.com/d/optout.