https://ramdajs.com/docs/#curry

接受一个函数

( → a) → ( → a)
Parameters
Added in v0.1.0
Returns a curried equivalent of the provided function. The curried function has two unusual capabilities. First, its arguments needn’t be provided one at a time. If f is a ternary function and g is R.curry(f), the following are equivalent:

  • g(1)(2)(3)
  • g(1)(2, 3)
  • g(1, 2)(3)
  • g(1, 2, 3)

Secondly, the special placeholder value R.__ may be used to specify “gaps”, allowing partial application of any combination of arguments, regardless of their positions. If g is as above and is [R._](https://ramdajs.com/docs/#), the following are equivalent:

  • g(1, 2, 3)
  • g(_, 2, 3)(1)
  • g(, , 3)(1)(2)
  • g(, , 3)(1, 2)
  • g(_, 2)(1)(3)
  • g(_, 2)(1, 3)
  • g(, 2)(, 3)(1)

    See also curryN, partial. ```javascript const addFourNumbers = (a, b, c, d) => a + b + c + d;

const curriedAddFourNumbers = R.curry(addFourNumbers); const f = curriedAddFourNumbers(1, 2); const g = f(3); g(4); //=> 10

  1. <a name="fwbK2"></a>
  2. # 提高了代码重用性
  3. I hope the last section gave you a taste of currying, as we’re dipping a bit more into it here.<br />Its main benefit is code reuse. Curried functions have a better chance of being useful in different scenarios, thus making them [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)er.<br />Let’s say you have an add function
  4. ```javascript
  5. const add = (x, y) => {
  6. console.log(`Adding ${x} and ${y}`);
  7. return x + y;
  8. };
  9. const result = add(2, 3);
  10. console.log({ result });

What happens if you don’t give add its required parameters? What if you give too little?

  1. const add = (x, y) => {
  2. console.log(`Adding ${x} and ${y}`);
  3. return x + y;
  4. };
  5. const result = add(2);
  6. console.log({ result });
  7. Adding 2 and undefined
  8. { result: NaN }

Not fun. You know this leads to weird bugs, especially in JavaScript where we do anything and everything. The problem sort of goes away when you curry add.

  1. import { curry } from 'ramda';
  2. const add = (x, y) => {
  3. console.log(`Adding ${x} and ${y}`);
  4. return x + y;
  5. };
  6. const curriedAdd = curry(add);
  7. // returns a function
  8. const result = curriedAdd(2);
  9. console.log({ result });
  10. //{ result: [Function] }

Your eyes don’t deceive you, curriedAdd(2) returns a function. It will keep returning a function until you supply the last parameter, y.

  1. import { curry } from 'ramda';
  2. const add = (x, y) => {
  3. console.log(`Adding ${x} and ${y}`);
  4. return x + y;
  5. };
  6. const curriedAdd = curry(add);
  7. const result = curriedAdd(2);
  8. console.log(
  9. result(),
  10. result(),
  11. result()
  12. );
  13. console.log("I won't stop returning functions until you give me Y! \n")
  14. console.log("Okay dude, here's y = 3...\n");
  15. console.log(result(3));
  16. console.log('\n-_-"')
  1. [Function] [Function] [Function]
  2. I won't stop returning functions until you give me Y!
  3. Okay dude, here's y = 3...
  4. Adding 2 and 3
  5. 5
  6. -_-"

传参可选—而不是一定要一个一个传

According to the FP books, currying means you return one new function per expected parameter.
So if you have an add3 or greet function

  1. const add3 = (x, y, z) => x + y + z;
  2. const greet = (greeting, first, last) => `${greeting}, ${first} ${last}`;

“Properly” currying them looks like this

  1. const curriedAdd3 = (x) => (y) => (z) => x + y + z;
  2. const curriedGreet = (greeting) => (first) => (last) => `${greeting}, ${first} ${last}`;

But let’s be honest, this sucks in JavaScript. I don’t want to call my functions like this

  1. curriedAdd3(1)(2)(3); // 6
  2. curriedGreet('Hello')('John')('Doe'); // Hello, John Doe

Thankfully Ramda’s curry supports either style. You can use them like above or give all the arguments at once.

  1. import { curry } from 'ramda';
  2. const greet = (greeting, first, last) => `${greeting}, ${first} ${last}`;
  3. const curriedGreet = curry(greet);
  4. // Supply all arguments at once
  5. const result1 = curriedGreet('Hello', 'John', 'Doe');
  6. // Or break it up
  7. const result2 = curriedGreet('Hello')('John')('Doe');
  8. // Get weird if you want
  9. const result3 = curriedGreet('Hello')()()()('John', 'Doe');
  10. // Store curried function as variable
  11. const greetJohn = curriedGreet('Hello', 'John')
  12. const result4 = greetJohn('Smith');
  13. console.log({
  14. result1,
  15. result2,
  16. result3,
  17. result4
  18. });
  19. /**
  20. { result1: 'Hello, John Doe',
  21. result2: 'Hello, John Doe',
  22. result3: 'Hello, John Doe',
  23. result4: 'Hello, John Smith' }
  24. **/

总结

  • Curried functions keep returning functions until all required parameters are given.
  • This lets you partially apply a function and create more specialized versions.
  • “Properly” curried functions return one function per argument. (a) => (b) => (c) instead of (a, b, c).
  • But they’re a bit impractical so Ramda lets you supply them normally, or one at a time.

普通函数转为柯里化函数

Create a function called defaultTo. It takes two parameters:

  • defaultVal: A default value
  • val: The value to return

If val is null or undefined, return defaultVal.
Else, return val.
Curry it to allow preloading arguments.

  1. import { curry } from 'ramda';
  2. const defaultTo =
  3. curry((defaultVal, val) => val == null ? defaultVal : val);