1:10 |> Filter(iseven) |> Map(sqrt) |> collect
Transducers have been introduced by Rich Hickey in Clojure and decouple the desired transformations, i.e., Map, Filter and so on, from the actual traversal (that’s why an explicit collect is needed above). Thereby the same transducer can be used across different data structures and do not create intermediate data structures, i.e.,
1:10 |> Filter(iseven) |> Map(sqrt) |> foldxl(+)
does not allocate.
Don’t know if Julia implements them for anything besides Iterators though. Clojure has some more options in this respect and supports transducers on channels for instance. ↩︎
There are many functions both in Base and across the data ecosystem that take a function argument and a data argument. Why add a special currying method to all of them, when this can be solved once and in a clean way using one of the “piping” packages?
I would recommend (my)DataPipes.jl (discourse thread) that has the main goal to make general data processing as convenient as possible. To my knowledge, DataPipes pipes have the least amount of code overhead compared to alternative packages. A basic example: @p rand(10) |> filter(<=(0.5)) |> map(_ + 1).
I think all of those can already be done via Base.Fix1(foo, bar), which fixes the first argument of foo to bar.
To be clear, we’d have to go to every function and add such a version manually, since automatic currying does not play nice with multiple dispatch. And adding these manually can run into the problem that e.g. map poses which would result in inconsistencies across functions, so either writing it explicitly or having a different name seems preferrable to me.
I’m also a bit puzzled by that overload too, i.e., it seems that map(f) is the same as f(). Independent of the name, i.e., zipWith, I fail to see you this is a consistent extension of map … in any case I would expect map(whatever) to return something iterable or a vector. Maybe I’m missing something here?