A Fallback for the JavaScript Pipeline Operator
Aldwin Vlasblom
Posted on January 6, 2021
Background
As I've also mentioned in my Introduction to Fluture, there's a tc39 proposal for inclusion of a "pipeline operator" into the JavaScript language.
This is great news for functionally-minded libraries such as Ramda, Sanctuary, Fluture, and many more. It also makes some vanilla JavaScript nicer, for example:
const input = '{"data": 1765}';
const answer = String(
Math.floor(
Math.sqrt(
JSON.parse(input).data
)
)
);
Becomes
const input = '{"data": 1765}';
const answer = input
|> JSON.parse
|> (x => x.data)
|> Math.sqrt
|> Math.floor
|> String;
Pretty neat, right? Well, sadly not everyone agrees. And it is because of this disagreement that the operator has still not made it into the language. What's worse, chances are that when it does make it -- if it does -- it will be in a form that is not half as useful for functional programming. I have argued as to why here, here, here in more depth, and very extensively over here.
The Fallback
That brings me to a small idea I had that allows us to write code much like the above, but in today's JavaScript. You can use it now, while waiting for a consensus to be reached, and in the future, in case the committee decides against the functional variant of the operator. This is what it looks like:
const input = '{"data": 1765}';
const answer = input
[o] (JSON.parse)
[o] (x => x.data)
[o] (Math.sqrt)
[o] (Math.floor)
[o] (String);
Very similar to the pipeline example from above! :)
This is how it can be achieved:
const key = Symbol('pipe');
global.o = key;
function pipe(f){ return f(this) };
Object.defineProperty(Object.prototype, key, {value: pipe});
Let's break this down.
-
Symbol('pipe')
: We define a unique symbol. We can use this to mutate existing objects without stepping on anyone's toes. -
global.o
: This is an optional convenience. In the browser, this should bewindow.o
. But you may just as wellexport const o
instead and import it where needed, so not to pollute the global scope. I choseo
as the name because it looks a bit like the mathematical composition operator (∘). -
function pipe
: All that the (simple) pipe operator does is to apply a function to its context. -
Object.defineProperty(...)
: We attach ourpipe
method to the Object prototype using our symbol as a key. This immediately retrofits almost all possible values (all the ones that inherit from Object) with our pipeline capabilities.
Alright, well, that's all there is to it. Let's hope that we won't have to use this trick (much longer).
Posted on January 6, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.