4 ms·
Not that I necessarily disagree, but one counter argument would be "why even use the pipe method? You could just say square(increment(square(2))) and get th
by mabbo 9y ago
Not that I necessarily disagree, but one counter argument would be "why even use the pipe method? You could just say
square(increment(square(2)))
and get the same result, right?"
The point is readability. It's UX for the programmer, reducing cognitive load in understanding what's going on. Pipes are fantastic in the terminal and have never been replaced there because they are very simple glue piecing together the complex bits with a simple-to-understand model.
If we can have that in JS, I'd be quite pleased even if there are other ways to do the same thing.
- djedr 9y agoThe counter argument would be wrong. The advantage of the operator and the `pipe` helper over regular function composition is that you can emphasize the flow of data through a pipeline of functions. The only advantage in readability I see here is that the operator is hard to mistake for anything else, it sticks out of the code, more than a seemingly regular function call. But this is not an advantage that justifies introducing the operator. Other than that, UX and cognitive load is the same. Pipes can indeed be fantastic! ;) * Apropos composition: why not add a composition operator while we're at it? Or we could define something like: const compose = (...args) => pipe(...args.reverse()) and then compose(square, increment, square, 2) ;) For me there is also something more ineffable that's important here. A question of whether adding a new built-in operator fits within the general philosophy or some sort of "look & feel" of the language, or whatever. I think JavaScript seems to be quite conservative, when it comes to bringing in new operators. Perhaps that's a good thing. Maybe not. But so far, I remain unconvinced.
- scottmf 9y agoHow would you add extra arguments to a function with your method?
- yladiz 9y agoYou could just make the function, like square, accept arguments and then return a function that can be composed in that way.
- scottmf 9y agoThat gives it a huge disadvantage over just using the pipe operator, particularly with standard functions: const pow = x => y => Math.pow(x, y); pipe(2, pow(5), square); compared to just: 2 |> Math.pow(5) |> square
- djedr 9y agoThe referenced operator proposal advocates the same solution[0] as @yladiz suggested here, so it's not clear to me where did you get this: 2 |> Math.pow(5) |> square from? This would mean the same thing as: Math.pow(5, 2) |> square right? This seems like a pretty hairy thing to implement into the language. Also I don't think this syntax is very clear. A more concise way of doing this with `pipe` would be: pipe(2, $ => Math.pow(5, $), square) Compared to the operator: 2 |> $ => Math.pow(5, $) |> square So no disadvantage at all. [0] https://github.com/tc39/proposal-pipeline-operator#user-content-functions-with-multiple-arguments https://github.com/tc39/proposal-pipeline-operator#user-cont...
- scottmf 9y agoOops, you're right. I was confusing the proposal with how it works in Elixir. I really like the partial application example from your source: let newScore = person.score |> double |> add(7, ?) |> boundScore(0, 100, ?); Partial application is a separate stage 1 proposal but together with the pipe operator I really prefer this: let x = 2 |> Math.pow(5, ?) |> square to this: let x = pipe(2, $ => Math.pow(5, $), square)