There’s already a proposal for partial application:
Let add7 = add(7, ?)
but creating partially applied functions is already fairly straightforward:
Let add7 = (a) => add(7, a)
Let boundScore100 = (a) => boundScore(0, 100, a)
let newScore = person.score
|> double
|> add7
|> boundScore100
As opposed to:
boundScore100(add7(double(person.score)))
The point is that composition doesn’t really make sense as an inline, once off thing. Composition is about function reuse and as a counterpoint to OO reuse mechanisms.
That said, all of this stuff works better with curried functions but JavaScript has never been a curried first language and has even moved further away from this by introducing defaults on arguments. That’s what comes from being a multi paradigm language I suppose.
Generally, piping operators are just a syntactic sugar easing the reading direction being in the same order than functional execution. It makes sense when you have a macro that just flips the order in the parsing process or if the language manages it.
But yeah, a desire to stay procedural and not functional. It makes us forget composition possibilities, like :
((o boundScore100 add7 double :score) person)
But, ok, it’s not in the right order 😀
so we can imagine
(-> person :score double add7 boundScore100)
But writing in this manner doesn’t give the same understanding.
I feel we could get pretty much anything we need in this space by adding curry(), curryN(), pipe() and compose() as native methods on the Array object.
The reading order is why I used to be interested in stack based languages and dataflow languages. I felt like there was something useful to be learned from them. (I always thought Smalltalk made more sense if you read each line backwards, for example.)
Stack based languages like Forth / Postscript certainly have a lot of power appeal especially on a tiny machine. The hard part though is managing the stack and cleaning up afterwards. Is there an elegant way to handle a closure? If there was then a functional approach (only one arg per call, curry the rest) might even make them manageable.
Oh yeah, that’s so much clearer. 🤦
https://plus.google.com/photos/…
LikeLike
This is a subject of contention in the discussion threads. The need for that syntax is for when functions have multiple arguments.
Functional programmers use single argument functions and prefer partial application and currying during composition.
The other side want to call their multi argument functions with default parameters.
In reality though I don’t see anyone wanting this operator who isn’t already trying to do functional composition.
LikeLike
There’s already a proposal for partial application:
Let add7 = add(7, ?)
but creating partially applied functions is already fairly straightforward:
Let add7 = (a) => add(7, a)
Let boundScore100 = (a) => boundScore(0, 100, a)
let newScore = person.score
|> double
|> add7
|> boundScore100
As opposed to:
boundScore100(add7(double(person.score)))
The point is that composition doesn’t really make sense as an inline, once off thing. Composition is about function reuse and as a counterpoint to OO reuse mechanisms.
LikeLike
That said, all of this stuff works better with curried functions but JavaScript has never been a curried first language and has even moved further away from this by introducing defaults on arguments. That’s what comes from being a multi paradigm language I suppose.
LikeLike
Generally, piping operators are just a syntactic sugar easing the reading direction being in the same order than functional execution. It makes sense when you have a macro that just flips the order in the parsing process or if the language manages it.
But yeah, a desire to stay procedural and not functional. It makes us forget composition possibilities, like :
((o boundScore100 add7 double :score) person)
But, ok, it’s not in the right order 😀
so we can imagine
(-> person :score double add7 boundScore100)
But writing in this manner doesn’t give the same understanding.
LikeLike
I feel we could get pretty much anything we need in this space by adding curry(), curryN(), pipe() and compose() as native methods on the Array object.
LikeLike
[double, add7, boundScore100].pipe(person.score)
Although pipe() should probably just return a high level function rather than applying itself to its argument.
LikeLike
The reading order is why I used to be interested in stack based languages and dataflow languages. I felt like there was something useful to be learned from them. (I always thought Smalltalk made more sense if you read each line backwards, for example.)
LikeLike
Stack based languages like Forth / Postscript certainly have a lot of power appeal especially on a tiny machine. The hard part though is managing the stack and cleaning up afterwards. Is there an elegant way to handle a closure? If there was then a functional approach (only one arg per call, curry the rest) might even make them manageable.
LikeLike