5
\$\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\$
9
  • \$\begingroup\$ What is the question? \$\endgroup\$ Commented Mar 3, 2016 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
    Commented Mar 3, 2016 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\$ Commented Mar 3, 2016 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
    Commented Mar 3, 2016 at 15:13
  • \$\begingroup\$ What's with the 0? That's not quite equivalent. \$\endgroup\$ Commented Mar 3, 2016 at 15:43

2 Answers 2

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)));
  }
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Nice answer. You can save a few chars by doing arguments = [].slice.call(arguments). \$\endgroup\$
    – Jonah
    Commented Mar 3, 2016 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.

\$\endgroup\$
1
  • \$\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\$ Commented Mar 5, 2016 at 16:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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