Your example falls apart when making multiple function calls.
third(z, second(y, first(x)))
With the pipeline operator (and assuming a language that allows partial application), the order in which things execute matches the order in which you read it: first x |> second y |> third z
The benefits start getting more noticeable when you're talking about stuff like manipulating sets of data. For example: myList
|> filter (x -> x.color == 'red')
|> sortBy (x -> x.count)
|> first
compared to these sorts of pyramids of doom: first(
sortBy(
x -> x.count,
filter(
x -> x.color == 'red',
myList
)
)
)64 |> Math.sqrt |> Math.sin becomes pipe(pipe(64, Math.sqrt), Math.sin)
Assuming pipe was smart and took varags we can make this better.
64 |> Math.sqrt |> Math.sin becomes pipe(64, Math.sqrt, Math.sin)
function pipe(val, ...funcs) {
for (let f of funcs) val = f(val);
}
EDIT: seems like I got ninja'd by an edit :) pipe(64,Math.sqrt,Math.sin)
and pipe(pipe(64, Math.sqrt), Math.sin)
are equivalent.pipe(val, func) => func(val)
then they wouldn't be equivalent but you absolutely could define pipe so they would be.
64 |> Math.sqrt |> Math.sin
Compiles in the AST to
Math.sin(Math.sqrt(64))
//curries variables away from functions
var realPipe = (a, ...args) => (...initParams) => {
var acc = a(...initParams);
for (var i = 0; i < args.length; ++i) {
acc = args[i](acc)
}
return acc;
}
//if first parameter is a function, curry to delay execution
//if first param is not a function, curry, but call immediately
var pipe = (a, ...args) =>
(typeof a === "function")
? realPipe(a, ...args)
: realPipe(...args)(a)
I'd note that this pipe implementation also bleeds its abstraction. JS has first-class functions, but this will never treat a function as data. You must be aware of how it works so if you are passing a function (for example, a getter function), you must manually curry it afterward.This complication is why most pipe implementations don't actually mess with that data attribute part (they just skip to the realPipe implementation), but since the pipe operator can handle it, I figured I'd try to as well to show the issues.