-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reconsider currying #6
Comments
Another question we should ask ourselves "Is point free actually a good thing?". Take a look at the example: foo(T.bar(x))
foo(y => T.bar(x, y)) In the second line one can tell much more about what is going on by just looking at the line itself, while to understand the first line they will need to check docs, other files, etc. |
Plan
|
@rpominov Currying and function composition are fundamental concepts of FP. Being point-free is just one property of them. static land makes
I guess this is merely micro-optimization. If you encounter serious performance penalties in a particular portion of your code, optimize that portion.
Good point.
Arrow functions provide a succinct syntax to manually define curried functions. No need for a programmatic solution.
Optional arguments are evil, just like variadic functions. With curried functions you simply don't need them: const f = opt => x => y => ...;
const g = f("whatsoever"); Would you re-reconsider currying? |
Before this issue, when currying was in the spec, it was required for all methods to support both You suggest a bit different approach to support only |
And this can really hurt performance actually. Consider some function like |
Another idea. Currying can be implemented as a library function that accepts a normal (current spec) static-land dictionary and returns a new one with curried methods. This way people could enjoy currying for any SL type without spec requiring it. |
First of all I think that the approach static land specifies will hit the big-time. I've played around a bit with an implementation and it actually solved problems and simplified code. Apart from the verbosity I haven't been faced with any drawbacks yet. Back to the topic: I don't want to be dogmatic here. My experience is that whenever I have an uncurried function in my toolset, I sooner or later re-implement it as a curried version. Also I've never experienced performance hits caused by currying so far. On the other hand I cannot assess the impact of currying on the spec or on corresponding implementations. Does it really matter? I would say yes, but that is rather intuitively. I need more experience. Your last suggestion sounds promising. Let's wait and see if currying is also an issue for others. |
Sounds good, @ivenmarquardt , let's wait for more feedback. Just one more option I want to mention, we always can use a helper like |
Like @ivenmarquardt, I also find myself currying functions as I am a proponent of the compositional / point-free style. Like anything, I think there is a balance to be struck when using point-free in regards to readability. |
Interesting article on stack-trace / debugging: https://medium.com/@drboolean/debugging-functional-7deb4688a08c#.7fv7ks3xn |
@rpominov Re; Additionally, JS now has a proposal for the reverse application inputObservable
|> Obs.map(x => x * 2)
|> Obs.flatMap(x => Obs.delay(1000, x))
|> Obs.filter(x => x < 50)
|> Obs.scan(x => y => x + y) |
@masaeedu Btw., you can have function composition with arbitrary number of curried functions along with simple recursion: // right to left
const comp = f => Object.assign(g =>
comp(x =>
f(g(x))),
{runComp: f});
// left to right
const pipe = f => Object.assign(g =>
pipe(x =>
g(f(x))),
{runPipe: f});
const inc = n => n + 1;
const sqr = n => n * n;
comp(sqr)
(inc)
(inc)
(inc)
(inc)
.runComp(0); // 16 I prefer this recursive encoding over the spread operator (e.g. |
I still feel like forcing everyone to call functions in weird way is not a good idea. I know many people are okay with it, but probably many will not be. Also performance issue still looks like a real issue to me. It's true that in most cases it won't matter, but if a curried function call appears in a hot path it will be a problem. I hope https://github.com/tc39/proposal-partial-application lands soon, seems like it solves all problems. |
Since the introduction of arrow functions, manually defining curried functions has become easy, and the only way to call const K = x => _ => x; is K(42)(null);
// or
K (42) (null); I'll admit it took me a little getting used to (a couple of days), but we're talking about a different programming paradigm here; the difference in calling patterns emphasizes this. |
Spaces are crucial. This expression would be difficult to read without spaces: B (B (B (B (eitherToMaybe)))) (encaseEither3 (I)) |
I don't want to start this discussion all over. I was just wondering if curried functions still conform to the spec as it was suggested by the original poster. The only hint in the specification is implicit in the section about module-signatures, where |
@RaoulSchaffranek You can define a function in a way that both |
The spec currently require that all methods of each type must be curried. Which is cool, but might be problematic sometimes.
Some problems are:
curry
functionWe could change the spec in a way that it won't require methods to be curried, but also won't require otherwise, so people could choose to use currying or not by themselves.
Related: #2
The text was updated successfully, but these errors were encountered: