Am Freitag, 17. Oktober 2014 04:02:52 UTC+2 schrieb Daniel James: > > Hi Michael, > > I’m glad you are in favor of this change; however, and with tongue firmly > in cheek, you’ve taken a beautiful thing and corrupted it, which I can’t > condone. ;) > > Let me offer an explanation as to why I half-jokingly say this. > > From what you’ve said, your “group-by-style transducer” is going to have > the following form: > > (fn [rf] > ([] {}) > ...) > > Irrespective of the rest of its implementation, it’s a function that > transforms a reducing function into another reducing function, but it is > most certainly *not* a transducer—a necessary, but not a sufficient > condition. > > Before I make an appeal to types, let me build some intuition by borrowing > the analogy that Rich Hickey made in his talk at Strange Loop. He was > saying that he wanted to give instructions to the baggage handlers about > how to handle the baggage, without having to say anything about whether the > baggage arrived on a trolley or by conveyor belt. By returning {} in the > 0-arity, you are effectively saying, “No, it’s definitely going to be on a > trolley!”. >
Hi Daniel, I'm not quite sure if your trolley-analogy is viable here (but see below). Please note that I'm working within a reduce scenario: a "conveyor belt" is moving data to the reducing function, and once the conveyor stops a single value is left behind -- the final result of the reducing fn. The grouping I am using does two things within this metaphor: in the one direction, it splits one conveyor into n independent conveyors; in the other direction, it combines n reduced results again into a single result. In code it looks like this: (defn group-by-xf [f] (fn [rf] (let [init (rf)] (fn ([] {}) ([result] (reduce-kv (fn [acc k v] (assoc acc k (rf v))) {} result)) ([result input] (let [k (f input) group-result (get result k init)] (assoc result k (rf group-result input)))))))) [...] > > > If I call > > (into [] xform (range 5)) > > (transduce xform + 0 (range 5)) > > I expect a vector and an integer to pop out, respectively, and I’m going > to be sorely disappointed if a map pops out instead! > > In this case you might prefer to write something like (transduce xform (comp group-by-xf +) ...) instead of (transduce (comp xform group-by-xf) + ...) . If I had used the first variant, then I would not have stumbled over the default init value of transduce at all. Mh. Seen this way, I only have to adjust my code accordingly and can continue to use the default init as it is. Thank you for this insight! > By the way, please, please, don’t read this as a polemic. I just want to > be precise about the issue, and I am certainly sympathetic to “While > experimenting I…”! > No offense taken. I do understand that beauty is always in the eye of the beholder. Using the grouping function above I was able to take a gnarly aggregation function (basically a multi level update-in plus a transformation on the leaves when done) and turn it into a sequence of group-by-xf plus a much simpler reducing fn. This is very beautiful to me ;-) -- Michael -- 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.