DEV Community

Discussion on: Future Javascript: Javascript Pipeline Operators

Collapse
peerreynders profile image
peerreynders • Edited on

Can anyone explain benefit of this?

In OO programming there is the concept of the fluent interface that allows you to chain method calls without needing intermediate assignments — this for example features prominently in the fluent builder patterm.

The disadvantage of this approach is that:

  • the method has to return an object (which in most cases is just simply this) and
  • the method the next "step" needs to perform has to be present on the returned object. So if you're dealing with with a third party object and you want to use your helper function then you are out of luck (unless you are OK which monkey patching the object first)

In value-oriented programming (most people call it functional programming though that definition is actually narrower) computation is advanced through the "transformation of values" rather than "flow of control".

So with pipelining you can use the "fluent chaining style" on any value including Primitve Values and objects without the required method/function.

Another way of writing

const calculate = addOne(multiplyByTwo(divideBySix(number)));
Enter fullscreen mode Exit fullscreen mode

is

const fns = [divideBySix, multiplyByTwo, addOne];
const calculate = fns.reduce((x, f) => f(x), number);
Enter fullscreen mode Exit fullscreen mode

The advantage with the second approach is that the function applications are now ordered left-to-right which many people find easier to read. The downside is the overhead of reducing an array of functions at runtime when the order and composition can fixed at design time ("Bake, don't fry"). Using the pipeline fixes the the reading order of the functions while not incurring any additional runtime overhead. Ideally the placeholder should be optional so that

const calculate = number |> divideBySix(%) |> multiplyByTwo(%) |> addOne(%);
Enter fullscreen mode Exit fullscreen mode

could be replaced with

const calculate = number |> divideBySix |> multiplyByTwo |> addOne;
Enter fullscreen mode Exit fullscreen mode

for single argument functions but I don't think that is even considered in the current proposal (ReScript has the advantage of resolving the placeholder at compile time; perhaps there are JS runtime performance concerns with an optional placeholder);

This way there are million different syntax offered by various language, bringing all in JavaScript will be complex.

Perhaps you are forgetting that JavaScript started out as "doing Scheme in the browser" — making it vaguely look like Java was a marketing stunt.

The later has better visibility and easy to debug.

Frankly that might simply be a result of your own familiarity bias. Most people who were taught imperative programming first, initially perceive functional programming as "less natural" and more difficult. But educator's experience has shown that is largely baby duck syndrome; in fact many students find it easier to start with functional programming first though there are always exceptions.

It should be no more difficult to follow the piped functions in the debugger or throw in a tee function.

const number = 6;
const fns = [divideBySix, multiplyByTwo, tee, addOne];
const calculate = fns.reduce((x, f) => f(x), number);

console.log(calculate);

function tee(x) {
  console.log(`tee: ${x}`);
  return x;
}

function addOne(x) {
  return x + 1;
}

function multiplyByTwo(x) {
  return x * 2;
}

function divideBySix(x) {
  return x / 6;
}
Enter fullscreen mode Exit fullscreen mode

Being imperatively minded also means thinking predominantly in "statements" as computation is about "place-oriented" data manipulation and "flow of control". Value-oriented programming relies heavily on "expressions" instead as computation is expressed as "transformations of values" and the pipe operator expands the expression toolkit.

The reason I am asking as I have written JavaScript engine for .NET,

Was F# ever considered as an option especially given that ML languages are considered to be good for writing compilers?

I understand that

  • hypothetically it should be easier to find C# contributors as F# programmers aren't as common
  • C# may currently have some performance advantages (e.g. asynchronous tasks)
  • C# seems like the safer choice

The issue is that there is already a precedent with Rhino. While it's still around, it seems to be languishing despite being based on something as "safe" and prevalent as Java. And Oracle has abandoned Nashorn in favour of supporting JS directly on GraalVM — removing Java as an intermediary.

Another approach would be to simply create a runtime that implements some smaller instruction set (like ES3) as generated by the Closure Compiler.

That said the pipeline operator proposal is only at Stage 2, with reservations as of August 2021 — so it may never happen and even in the best case wouldn't enter the spec until 2023 at the earliest.

I would imagine that Pattern Matching would cause a lot more work than the pipeline operator.

Collapse
akashkava profile image
Akash Kava

Thanks for detailed answer, I do find sequence of functions in correct order as important thing as nested function calls are evaluated from depth first order.