I wrote another library, called pipeline_func
, that might be of interest to those in this discussion. Here’s what it’s looks like in action:
>>> from pipeline_func import f, X
>>> a = [3, 4, 2, 1, 0]
>>> b = [2, 1, 4, 0, 3]
>>> a | f(zip, b) | f(map, min, X) | f(filter, bool, X) | f(sorted)
[1, 2, 2]
f
is a class that wraps any arbitrary callable and implements the pipe syntax. X
is an object that stands in for the output from the previous step, thereby accommodating functions like filter
and map
where the iterable is the second argument. By default, though, the first argument to the current step is the output from the previous step.
The X
abstraction isn’t perfect; it doesn’t work if X
is contained in another object (e.g. a list or a dict). To my knowledge, there’s no way to make an object that replaces itself with some other object the first time it’s accessed, which I think is what’s needed here. Maybe that would be a useful feature request for python itself. (It would be possible to replace X
in nested data structures by pickling/unpickling each argument, but this would be way too much overhead.)
I’m probably biased, but I think this is a pretty nice syntax already. Here’s an example of what it looks like in a real project, which I think is a little easier to understand than the contrived example above.