Thank you all and especially @James. That is exactly what I'm missing. Thanks again for help.
On Wednesday, September 24, 2014 5:51:09 PM UTC+2, James Reeves wrote: > > Reducers primarily have two benefits: > > 1. You don't need to create intermediate seqs > 2. You can use them to perform a parallel fold > > When you use clojure.core/map, it creates a lazy seq. When you use > clojure.core.reducers/map, it returns a small reified object that > implements CollReduce. > > Perhaps the best way to understand what's going on is to start with the > normal seq functions. For instance, consider this code: > > (let [ys (map inc xs)] > (filter even? ys)) > > In this example, an intermediate seq, ys, needs to be constructed. > > We can avoid this intermediate seq by using a reduce that combines both > steps: > > (reduce (fn [r x] (if (even? x) (conj r (inc x)) r) [] xs) > > The problem with this approach is that it's rather complected. What we > need is something that resolves to a reduce, but can be combined like map > and filter. This is where reducers come in. > > The main idea is to factor out that pesky conj, so we can separating the > reduction from the implementation details of the collection. So we can take > the inner reducing function: > > (fn [r x] (if (even? x) (conj r (inc x)) r) > > And then factor out conj: > > (fn [f] (fn [r x] (if (even? x) (f r (inc x)) r)) > > We can then split out the filter and map to get two functions > > (fn [f] (fn [r x] (if (even? x) (f r x) r)) > (fn [f] (fn [r x] (f r (inc x))) > > And then take out even? and inc to get generic filter and map functions: > > (defn filterer [xf] (fn [f] (fn [r x] (if (xf x) (f r x) r)) > (defn mapper [xf] (fn [f] (fn [r x] (f r (xf x))) > > So now we have the essence of map and filter, but we've removed the > implementation details of the collection. > > Next we just need to figure out how to use these highly abstracted > functions. If we just want to use one of the functions, we can do so like > this: > > ((mapper inc) conj) > > This returns a function: > > (fn [r x] (conj r (inc x))) > > If we want to combine map and filter, we need an expression like: > > (fn [r x] (if (even? x) (conj r (inc x)) r)) > > We can do this by passing the result of the mapping function into filterer > as f: > > ((filterer even?) ((mapper inc) conj)) > > Or, we could use comp to compose the two functions, then apply conj, since > (f (g x)) is the same as ((comp f g) x): > > ((comp (filterer even?) (mapper inc)) conj)) > > Now we can can finally create our efficient map/filter in a clean way: > > (let [f (comp (filterer even?) > (mapper inc))] > (reduce (f conj) [] xs)) > > The reducer library goes one step further, and uses protocols to make it a > little nicer to use, but the mechanics are more or less the same. > > - James > > > On 24 September 2014 15:30, Hussein B. <hubag...@gmail.com <javascript:>> > wrote: > >> To elaborate more, >> I know that with reducers, map for example isn't going to create the >> resulting sequence by using cons. That is clear to me. >> But, if the collections is going to call cons while reducing itself, then >> I'm not sure what is the benefit of reducers (besides it makes sense and >> makes a nice abstraction). >> >> Thanks. >> >> On Wednesday, September 24, 2014 2:58:18 PM UTC+2, Aleš Roubíček wrote: >> >>> Resulting function is passed to reduction function as an recipe, how to >>> process the data. Collections implements CollReduce protocol. When you call >>> reduce function it will delegate the work to concrete implementation of the >>> protocol. >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clo...@googlegroups.com >> <javascript:> >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+u...@googlegroups.com <javascript:> >> 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+u...@googlegroups.com <javascript:>. >> 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.