Please explain.
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 :) 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.
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.