functional programming - Function application for curried functions in JavaScript and ES6 -


i love ecmascript 6 allows write curried functions this:

var add = x => y => z => x + y + z; 

however, hate need parenthesize every argument of curried function:

add(2)(3)(5); 

i want able apply curried functions multiple arguments @ once:

add(2, 3, 5); 

what should do? don't care performance.

currying , application of curried functions controversial issues in javascript. in simple terms, there 2 opposing views, illustrate both briefly.


- use of separate curry function when necessary

the adaptation of concepts other languages or paradigms in principle thing. adaptation though, should done elementary means of target language. mean currying in javascript?

  • curried functions called sequence of unary functions:add3(1)(2)(3); // 6
  • own functions manually curried arrows const add3 = x => y => z => x + y + z;
  • third party functions or methods curried separate curry function

- use of separate curry implementation default

there's problem proposed $/uncurry function:

const $ = (func, ...args) => args.reduce((f, x) => f(x), func); const sum = x => y => z => x + y + z;  $(sum, 1, 2, 3); // 6 $(sum, 1, 2)(3); // 6 $(sum, 1)(2, 3); // z => x + y + z 

in way uncurried functions can once applied unlimited number of arguments. subsequent calls must made unary. function promises. however, not allow application of curried functions, such javascript developers used to. of current curry implementations more flexible. here's extended implementation:

const uncurry = f => (...args) => args.reduce(   (g, x) => (g = g(x), typeof g === "function" && g.length === 1    ? uncurry(g)     : g), f );  const sum = uncurry(x => y => z => x + y + z);  sum(1, 2, 3); // 6 sum(1, 2)(3); // 6 sum(1)(2, 3); // 6 

this implementation works, if auto-uncurrying: once uncurried function produces curried function return value, returned function automatically uncurried. if prefer more control, following implementation might more appropriate.

the final uncurry implementation

const partial = arity => f => function _(...args) {   return args.length < arity    ? (...args_) => _(...args.concat(args_))    : f(args); };  const uncurry = arity => f => partial(arity)(args => args.reduce((g, x) => g(x), f)); const sum = uncurry(3)(x => y => z => x + y + z);  sum(1, 2, 3); // 6 sum(1, 2)(3); // 6 sum(1)(2, 3); // 6 

this tiny arity parameter brings desired control. think it's worth it.

a curry solution rest

what functions beyond our control , hence haven't been manually curried?

const curryn = uncurry(2)(arity => f => partial(arity)(args => f(...args))); const add = curryn(2, (x, y) => x + y); const add2 = add(2);  add2(4); // 6 

fortunately, able reuse partial , keep curryn concise. solution variadic functions or such optional parameters can curried.

bonus: "funcualizing" , currying methods

to curry methods, need transform nasty, implicit this property in explicit parameter. turns out can reuse partial adequate implementation once again:

const apply = uncurry(2)(arity => key => {   return arity    ? partial(arity + 1)(args => args[arity][key](...args.slice(0, arity)))    : o => o[key](); });  apply(0, "tolowercase")("a|b|c"); // "a|b|c" apply(0, "tolowercase", "a|b|c"); // "a|b|c"  apply(1, "split")("|")("a|b|c"); // ["a", "b", "c"] apply(1, "split")("|", "a|b|c"); // ["a", "b", "c"] apply(1, "split", "|", "a|b|c"); // ["a", "b", "c"]  apply(2, "includes")("a")(0)("a|b|c"); // true apply(2, "includes", "a", 0, "a|b|c"); // true 

in blog post currying discussed in detail.


Comments

Popular posts from this blog

Delphi XE2 Indy10 udp client-server interchange using SendBuffer-ReceiveBuffer -

Qt ActiveX WMI QAxBase::dynamicCallHelper: ItemIndex(int): No such property in -

Enable autocomplete or intellisense in Atom editor for PHP -