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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.