Re:Reducers, transducers and core.async in Clojure
by whalesalad on Wednesday June 07, 2017 @11:33AM
(#14507253)
You can compose it all together in a relatively straightforward manner using functions in the stdlib. I agree that it is nicer with a threading macro, but is this so bad?
def even(x):
return x % 2 == 0
def inc(x):
return x + 1
def process(seq):
return sum(map(inc, filter(even, seq)))
Re:Reducers, transducers and core.async in Clojure
by emidln on Wednesday June 07, 2017 @11:58AM
(#14507430)
You can also easily write pipeline() (which is just a reduction over callables inside a lambda[0]) such that:
process = pipeline(partial(filter, even),
partial(map, inc),
sum)
process(some-iterable)
I'll grant that it's not syntactically ideal (this is the tradeoff the thrush combinator (pipeline) running as a function instead of working as a macro. The benefit of being able to follow down the program as it works remains. (def process [xs]
(->> xs
(filter even?)
(map inc)
(reduce +)))
(process some-iterable)
If you compare a function-based approach[1] (instead of a macro) you might get: (def process
(pipeline
(partial filter even?)
(partial map inc)
(partial reduce +)))
process(some-iterable)
[0] A sample Python definiton (python doesn't have compose to reverse): def pipeline(*fns):
return reduce(lambda f, g: lambda *xs, **ys: g(f(*xs, **ys)), fns)
[1] A clojure implementation: (defn pipeline [& fs] (apply compose (reverse fs)))
The other point in the article was that your process has now hard-coded even and sum, and composing them in python is a bit unwieldy.
I've run into a number of cases where it's just easier in python to write out the loops than string comprehensions or map/filter/reduces together because there's no threading macro or haskell's functional apply operator.