There's been talk of this before here and in
https://github.com/gilbert/es-pipeline-operator among other places. Most
recently this was posted, which sounds like promising progress:
https://github.com/gilbert/es-pipeline-operator/issues/33#issuecomment-306986211

On Tue, Jul 11, 2017 at 1:02 PM, David White <[email protected]>
wrote:

> Piping is useful when composing many small pure functions together, one
> problem with this is the evaluation needs to be read from the inner most
> expression value in reverse to the outer most function call. Given the
> following statement we can see that it would be read as 'call math round
> then call math square then pass in PI', whereas the order of execution is
> in reverse.
>
> ```javascript
> const myNumber = Math.round(Math.sqrt(Math.PI));
> ```
>
> Unix has long provided a piping mechanism to achieve that, for example:
> `ps aux | grep node`, as well as F# and the Elixir programming language,
> both provide the `|>` pipe greater-than operator which is very readable.
>
> My proposal would be to use the slightly more verbose `|>` pipe-greater
> than syntax, it provides a convenient direction of travel for the
> expression on the left side, into the expression on the right, F# also
> provides a `<|`, which pipes in the opposite direction though I’ve not
> really seen very good use cases for this operator.
>
> ```javascript
> const myNumber = Math.PI |> Math.sqrt |> Math.round;
> ```
>
> The left side of the operator should always be a primitive data type or
> data structure, these could be any of the following: `Boolean`, `Null`,
> `undefined`, `Number`, `String`, `Symbol` or `Object`. Since functions are
> standard objects they can be passed in as the initial value, as long as the
> function on the right handles the calling on that function.
>
> It also provides a way to either log, process, or do anything with the
> data from the last expression on the left at various stages of the
> execution without adding additional brackets in and around the calls, for
> example.
>
> ```javascript
> function logger (callback) {
>   return function (value) {
>     callback(value);
>     return value;
>   };
> }
>
> Math.PI
>   |> logger(console.log);
>   |> Math.sqrt
>   |> logger(console.log);
>   |> Math.round
>   |> logger(console.log);
> ```
>
> While a slightly contrived example as we certainly wouldn't write code
> that looks like:
>
> ```javascript
> logger(Math.round(logger(Math.sqrt(logger(Math.PI)))));
> ```
>
> We would instead assign to variables at each stage of execution:
>
> ```javascript
> const PI = Math.PI;
> logger(PI);
>
> const squaredPI = Math.sqrt(PI);
> logger(squaredPI);
>
> const roundedSquaredPI = Math.round(squaredPI);
> logger(roundedSquaredPI);
> ```
>
> However with this clarity we have unfortunately had to create additional
> constants within this lexical block, whereas simple value passing between
> pure functions provides a very clean and readable approach and allows
> easier updates in the future if we wanted to add additional processing
> within the chain, for example Express middleware composition.
>
> Would love to hear some thoughts on this?
>
> David
>
> * [F# pipe operator](https://docs.microsoft.com/en-gb/dotnet/
> fsharp/language-reference/functions/index#function-
> composition-and-pipelining)
> * [Elixir pipe operator](https://elixir-lang.org/getting-started/
> enumerables-and-streams.html#the-pipe-operator)
> * [Unix pipeline](https://en.wikipedia.org/wiki/Pipeline_(Unix))
>
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to