0

I am reading right now the source code of Ramda and don't understand the point of _curry1().

function _curry1(fn) {
  return function f1(a) {
    if (arguments.length === 0 || _isPlaceholder(a)) {
      return f1;
    } else {
      return fn.apply(this, arguments);
    }
  };
}

Functions that are curried with this function can be called without arguments.

const inc = (n) => n + 1
const curriedInc = _curry1(inc)

// now it can be called like this
curriedInc(1)   // => 2
curriedInc()(1) // => 2

// but it works only with no arguments provided
const add = (a, b) => a + b
const curriedAdd = _curry1(add)

curriedAdd(1)     // => NaN
curriedAdd(1)(1)  // => TypeError: curriedAdd(...) is not a function
curriedAdd()      // => function f1(a)

Question: It seems to me that you can't chain arguments with this function at all. What are use cases for this function? How different is curriedInc()(1) from inc(1)?

customcommander
  • 17,580
  • 5
  • 58
  • 84
pdlmn
  • 5
  • 3
  • Does this answer your question? [What is 'Currying'?](https://stackoverflow.com/questions/36314/what-is-currying) – Luca Kiebel Jan 12 '22 at 17:13
  • 3
    It probably exists for performance or compatibility reasons. You shouldn't bother yourself about internal stuff. –  Jan 12 '22 at 17:39
  • 1
    `_curry1` is internal, you should use the public-facing function [`curry`](https://ramdajs.com/docs/#curry) instead. – customcommander Jan 12 '22 at 17:42
  • as the name suggests, it curries unary (single argument) functions, so as you figured it out by yourself, it doesn't work with multi-argument functions. – marzelin Jan 12 '22 at 17:48
  • @IvenMarquardt I understand that `_curry1()` is internal function, but it used *a lot* for different functions. It can be hard to understand the code of functions intended for use without understanding some of the internals. – pdlmn Jan 12 '22 at 18:07

1 Answers1

4

_curry1, _curry2, and _curry3 are performance-boosting tricks that can't be used in the public curry function. Ramda (disclaimer: I'm an author) uses them to perform several tasks, clearly mostly doing the currying, but also checking for placeholders so that we can properly do some partial application. The other magic thing about Ramda's currying is the way that you can apply all, some, or even none of the required arguments, and so long as we're not complete, you get back another function looking for the remaining ones.

Obviously _curry1 theoretically shouldn't be necessary, but it makes it easier to add this sort of consistency:

const a = curry ((a, b, c) => ...)
a (1, 2, 3) == a (1, 2) (3) == a (1) (2, 3) == a (1) (2) (3) == a () () (1, 2) () (3)

Notice that last one. When you call a curried function still looking for arguments with no arguments at all, you get back the same function.

curry1 is what makes that happen; it adds consistency. But that's all it's for.

Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
  • "*or even none*" - does that have any practical applications? Or is it also just for theoretical completeness? – Bergi Jan 12 '22 at 20:38
  • 2
    @Bergi: just theoretical. It makes no practical difference, and the two cofounders disagreed on this point. I won. :-) This to me is similar to `sum ([]) //=> 0` or `n ** 0 //=> 1`. – Scott Sauyet Jan 12 '22 at 20:44