5 ms·
This is one of my favorite proposals, along with the pipe operator and partial application proposals: const add = (x, y) => x + y; const addTwo = add(2, ?)
by scottmf 9y ago
This is one of my favorite proposals, along with the pipe operator and partial application proposals:
const add = (x, y) => x + y;
const addTwo = add(2, ?);
let x = addTwo(5); // 7
x = 5 |> addTwo |> add(?, 10); // 17
The last example is equivalent to:
add(addTwo(5), 10);
Obviously the pipe operator is more useful when order matters.
- dvlsg 9y agoI wouldn't mind seeing forward and reverse composition operators (so >> and << from F#) as well. But getting pipe would be a pretty awesome first step.
- scottmf 9y agoLooks like there’s a recent proposal for them: https://github.com/TheNavigateur/proposal-pipeline-operator-for-function-composition https://github.com/TheNavigateur/proposal-pipeline-operator-...
- am_i_legal 9y agothis looks... like F#?
- scottmf 9y agoYes, it’s inspired by the pipe operator in languages like F#.
- contras1970 9y agokinda already possible: const bind1st = (f, x) => (y) => f(x, y) const addTwo = bind1st(add, 2) let x = addTwo(5) // 7 it can get a little confusing unless one's used to point-free programming: const twostep = bind1st(bind1st, bind1st) // YMMV
- mafro 9y agoAlthough I expect you're presenting a contrived example, I find that syntax horrible. In your example it provides no additional value, and requires more typing. And more thinking to parse.
- geoelectric 9y agoWhich aspect, the partial or the pipeline? The partial application operator clearly wins over bind, IMO, which is currently the way you'd do that [ addTwo = add.bind(this, 2) ] if only because you don't need to specify the this parameter. It also gives the option to "bind" to other parameters than the leftmost. The pipeline operator in that example is a little contrived, but coming from any functional background it makes a ton of sense. Depending on what I was piping, I might also format it more like: x = 5 |> addTwo |> add(?, 10) ...which would probably resonate with anyone used to promise chains: x = Promise.resolve(5) .then(addTwo) .then(add(?, 10)) // or v => add(v, 10) It's still contrived, but it is a reasonably familiar flow in JS. It would also clean up async/await syntax a lot assuming they could be used together: x = await foo(await bar(2, await baz(3))) ...becomes... x = await baz(3) |> await bar(2, ?) |> await foo(?) ...which honestly is a more accurate representation of what's happening.
- mafro 9y agoThanks for the expanded examples. Maybe I'll like it once I see it in the wild solving real problems.
- scottmf 9y agoThe point is it looks a lot better than several nested function calls, especially when the order of the calls are important. In JS you can do stuff like this: const rules = parsedTags .split(';') .map(item => item.trim()) .filter(item => !!item); But in some functional languages you would have to do something like this: Array.filter(Array.map(String.split(parsedTags, ';'), item => String.trim(item)), item => !!item); Which makes it a lot more difficult to write/understand. (Note the order in which the functions will be called). With a pipe operator you can do something like this: parsedTags |> Array.split(';') |> Array.map(item => String.trim(item)) |> Array.filter(item => !!item); Now that people are writing more functional JS, a pipe operator becomes much more useful since you can't always chain function calls like the JS example above.