Reputation: 22530
In the following example, I couldn't get Ramda.js uncurry functions to work with ES6 arrow functions when a default parameter is present:
const tt = (x) => y => x + y;
const tt1 = (x = 5) => y => x + y;
const uncurry = R.uncurryN(2);
console.log( uncurry(tt)(1,2) );
console.log( uncurry(tt1)(1,2) );
The two functions tt
and tt1
should be the same except for a default parameter. But The output is different (babel-node 6.24.1):
3
6
It seems that the default syntax is taken as an assignment with the uncurrying.
Am I missing something here? Is this intended or a bug?
Just to clarify:
Without the curry/uncurry, both functions (with or without the default value), behaves the same way when parameters are fully supplied. Both tt(1)(2)
andtt1(1)(2)
evaluates to 3
. Why should the behavior be different after changing calling convention?
By the way, I was following some react/redux examples (es6 how to use default parameters that go before non-default parameters?) and test if it's possible to convert some of the react function calls to Ramda style. The issue discussed here is apparently an obstacle.
Upvotes: 3
Views: 1156
Reputation: 50807
While this isn't precisely intended, it's hard to see a really useful solution to this.
The fault is in this line in the implementation:
endIdx = currentDepth === depth ? arguments.length : idx + value.length;
If it were replaced with
endIdx = currentDepth === depth ? arguments.length : idx + 1;
your two functions would work the same. That would then break this sort of usage:
const tt2 = (x, y) => (z) => x + y + z;
uncurry(tt2)(1, 2, 3); //=> NaN
(With the current implementation, this properly returns 6
.)
That might not be all that important. It seems a strange thing to try to use uncurryN
for a function that is not fully curried.
But overall, I don't know that this helps. Default parameters can be difficult to work with. A parameter with a default does not contribute to the function's length
:
length
is a property of a function object, and indicates how many arguments the function expects, i.e. the number of formal parameters. This number excludes the rest parameter and only includes parameters before the first one with a default value. -- MDN
The default values are not available for use by decorator functions, so something like uncurryN
would lose the default values. And it makes it awkward to work with any parameters after one with a default value.
You could still do this, of course:
((x, y) => tt1(x)(y))(1, 2); //=> 3
((x, y) => tt1(x)(y))(undefined, 2); //=> 7
And an undefined
passed to uncurry(tt1)
would work as well. But passing an explicit undefined
feels a bit odd.
Feel free to raise an issue for Ramda to discuss this.
You can play with these ideas on the Ramda REPL.
Upvotes: 1