
On Sat, Nov 27, 2021 at 02:58:07AM -0000, Raimi bin Karim wrote:
This syntactic sugar imo is powerful because it's not limited to iterables but generalises to possibly any object.
Indeed. There is no reason to limit pipelines to only collections, any object which can be transformed in any way will work.
But I guess since method chaining (for collection pipeline) is more commonplace across many languages, it might be easier to catch on.
We should be careful about the terminology. Method chaining and pipelining are related, but independent, design patterns or idioms: Method chaining or cascading, also called fluent interfaces, relies on calling a chain of methods, usually of the same object: obj.method().foo().bar().baz().foobar() This is very common in Python libraries like pandas, and in immutable classes like str, but not for mutable builtins like list. So it is very simple to implement chaining in your own classes, by having your methods either return a new instance, or by returning self. Just don't return None and you'll probably be fine :-) Pipelining involves calling a sequence of independent functions, not necessarily methods: obj | func | spam | eggs | cheese | aardvark In mathematical notation, using the ring operator for function composition, that is the same as: (func∘spam∘eggs∘cheese∘aardvark)(obj) In concatenative languages like Factor or Forth, you would write it in reverse polish notation (no operator required): obj func spam eggs cheese aardvark compared to regular function notation, where functions are written in prefix order, which puts them in the reverse of executation order: aardvark(cheese(eggs(spam(func(obj))))) Even though they logically go together in some ways, let's be careful to not confuse these two idioms. Note that chaining, pipelining and function composition go together very well: (obj.method().foo() | func∘spam | eggs).bar().baz() executes from left-to-right, exactly as it is written. (Assuming that the ring operator has a higher precedence than the pipe operator, otherwise you can use parentheses.) Contrast how well that reads from left to right compared to: eggs(spam(func(obj.method().foo()))).bar().baz() where the order of executation starts in the middle, runs left to right for a bit, then back to the middle, runs right to left, then jumps to the end and runs left to right again. -- Steve