DEV Community

Meghan (she/her)
Meghan (she/her)

Posted on

I made a JS Module so you can *almost* use the pipeline operator today!

I heard you like functions so I made a function for you to pipe your functions to other functions functionally.

TC39, the standards body for ECMAScript, currently has a proposal for the pipeline operator in Stage 1 that's gaining a lot of traction.

Suppose you have the following function declarations

function doubleSay (str) {
    return str + ", " + str;
}
function capitalize (str) {
    return str[0].toUpperCase() + str.substring(1);
}
function exclaim (str) {
    return str + '!';
}
Enter fullscreen mode Exit fullscreen mode

So if you wanted to use the functions together, you could do:

let result = exclaim(capitalize(doubleSay("hello")));
Enter fullscreen mode Exit fullscreen mode

But that executes all of our functions in the backwards order that we wrote them, so introducing the pipeline operator!

let result = "hello"
  |> doubleSay
  |> capitalize
  |> exclaim;
Enter fullscreen mode Exit fullscreen mode

That looks much better! And there's a lot of discussion about the exact syntax and whatnot, but whilst reading said discussion, someone mentioned that this is actually already possible with JavaScript! So I did some research, tested it, and wrapped it up, and this is the core result :D

function pipeline(input, ...methods) {
    const next = methods.shift();
    if (typeof next !== 'function') {
        return input;
    }
    return pipeline(next(input), ...methods);
}
Enter fullscreen mode Exit fullscreen mode

And that's it! And then to use this we would do,

let result = pipeline(
  "hello",
  doubleSay,
  capitalize,
  exclaim
);
Enter fullscreen mode Exit fullscreen mode

But this is #showdev so I made a module and you can use this today!

Note: At the time of this writing ES 2015+ Module support on Node and Firefox is experimental so your mileage may vary depending on your platform. Issues and comments on GitHub welcome :)

Links:


edit: Thanks to advice, this is now also available as a 1-liner that take advantage of Array.reduce!

const pipeline = (input, ...methods) => methods.reduce((ac,cv) => cv(ac), input);
Enter fullscreen mode Exit fullscreen mode

Oldest comments (3)

Collapse
 
dmerand profile image
Donald Merand

Excellent solution! If you want to crank the functional up to 11, try implementing it as a reducer ;)

Collapse
 
nektro profile image
Meghan (she/her)

Excellent idea! I'll look into that :D

Collapse
 
1hko profile image
1hko

Nice work. This sort of exercise is great because it shows us that syntax is often nothing other than sugar. Everything is possible with lambda.

Another encoding that allows you to chain any amount of functions

const pipeline = x => f =>
  pipeline (f (x))

pipeline ("hello") (doubleSay) (capitalize) (exclaim) (console.log)
// Hello, hello!

pipeline ("hello") (exclaim) (exclaim) (exclaim) (exclaim) (console.log)
// hello!!!!