4
\$\begingroup\$

I am new to the functional style, and I wrote a curry function to practice this new style. This curry function takes a regular function and returns the curried version of it. Currying is a technique, with which you can partially evaluate functions.

function curry(f, self) {
  return function () {
    if (arguments.length == f.length) {
      return f.apply(self, arguments);
    }
    arguments = Array.prototype.slice.call(arguments);

    return curry(f.bind.apply(f, [self].concat(arguments)));
  }
}

function f(a, b, c, d) {
  return this + a + b + c + d;
}

document.write("f(1, 2, 3, 4) = ", curry(f, 0)(1, 2, 3, 4), "<br>");
document.write("f(1, 2, 3)(4) = ", curry(f, 0)(1, 2, 3)(4), "<br>");
document.write("f(1)(2, 3, 4) = ", curry(f, 0)(1)(2, 3, 4), "<br>");
document.write("f(1)(2)(3)(4) = ", curry(f, 0)(1)(2)(3)(4), "<br>");

\$\endgroup\$
  • \$\begingroup\$ What is the question? \$\endgroup\$ – Piero Divasto Mar 3 '16 at 14:27
  • 1
    \$\begingroup\$ Guys, currying is a well known JavaScript technique, you are simply not the target audience ;) I spruced up the question for curious readers. \$\endgroup\$ – konijn Mar 3 '16 at 14:45
  • 1
    \$\begingroup\$ I took a quick look on javascript.crockford.com/www_svendtofte_com/code/…. Its solution looks more complicated than mine. Have I missed some use case? \$\endgroup\$ – Rodrigo5244 Mar 3 '16 at 14:53
  • \$\begingroup\$ What is the selfargument used for? Can't you use this if it's not defined? (and allow something like curry(f)(0). \$\endgroup\$ – oliverpool Mar 3 '16 at 15:13
  • \$\begingroup\$ What's with the 0? That's not quite equivalent. \$\endgroup\$ – 200_success Mar 3 '16 at 15:43
4
\$\begingroup\$

Interesting question,

your code is very close to the code here : http://blog.carbonfive.com/2015/01/14/gettin-freaky-functional-wcurried-javascript/

I prefer your lack of else since your if block has a return anyway.

I would name the anonymous function, anything is better than 'anonymous function' when debugging.

function curry(f, self) {
  return function curriedFunction() {
    if (arguments.length == f.length) {
      return f.apply(self, arguments);
    }
    arguments = Array.prototype.slice.call(arguments);
    return curry(f.bind.apply(f, [self].concat(arguments)));
  }
}
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Nice answer. You can save a few chars by doing arguments = [].slice.call(arguments). \$\endgroup\$ – Jonah Mar 3 '16 at 21:20
1
\$\begingroup\$

I try since yesterday to understand this:

He makes a new copy of f by using bind(). He assigns the parameter already provided but what is with the self.

Let me try to explain:

// Second parenthesis (marked with =>): There are three of four  
// expected parameter provided: 
document.write("f(1, 2, 3)(4) = ", curry(f, 0) => (1, 2, 3) <= (4), "<br>");

// Makes an array-literal with 0 as only element in it.
// Then adds the parameter already provided to these array.
// => Must result in an array [ 0, 1, 2, 3 ].
// Then makes a new copy of f with these values bind to it as parameter.
return curry(f.bind.apply(f, [self].concat(arguments)));

f should now have it's four parameter. It should be executed and resulting "return 0 + 0 + 1 + 2 + 3;" and return 6.

Why isn't that the case?

Perhaps someone can answer that. I would appreciate it.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ The first argument of bind is used as the value of this inside the new function, so the first element of the array passed to apply is going to be used as the value of this in the function. The other elements in the array are arguments. \$\endgroup\$ – Rodrigo5244 Mar 5 '16 at 16:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.