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

