Curried functions

# Niloy Mondal (9 years ago)

It would be really cool to have syntax to curry functions built into the languages. Something like...

curry function add(a, b) {
    return a + b;
}

add(2)(3); // 5
# Mark S. Miller (9 years ago)

const add = a => b => a + b;

# Yongxu Ren (9 years ago)

How about making arrow function curry by default?

const add = a => b => a + b;

this will only works in case

add(a)(b);

But it won’t work if you do this

add(a,b);

If we could let arrow to work for both

add(a)(b) and add(a,b)

it will release the full power of functional programming and allow us to write code like in OCaml, F# or Haskell

# Michael McGlothlin (9 years ago)

I dislike that syntax because it makes the order of operations mysterious. I like the idea of currying but it should always be clear what is going on. A couple parentheses would make things a lot more obvious.

# Alexander Jones (9 years ago)

Too late, add(a) already returns a + undefined.

No reason why const add = curry((a, b) => a + b) couldn't work though?

Arrow functions have a length property AFAIK.

# Yongxu Ren (9 years ago)

Sorry I actually didn’t mean to use this for currying

const add = a => b => a + b;

This was directly copied from Mark's example, I was thinking about making the non-nested arrow functional. My idea is if you define

const add = (a,b) => a + b;

you will be able to use either add(a,b) or add(a)(b)

# Jeremy Darling (9 years ago)

If I understand your question correctly, your asking if fat arrow functions could be auto curried? I think this would be great, but anything using ...rest arguments could never be curried without finalization.

# Waldemar Horwat (9 years ago)

On 10/15/2015 12:58, Yongxu Ren wrote:

Sorry I actually didn’t mean to use this for currying

const add = a => b => a + b;

This was directly copied from Mark's example, I was thinking about making the non-nested arrow functional. My idea is if you define

const add = (a,b) => a + b;

you will be able to use either add(a,b) or add(a)(b)

Alexander's point still stands. This would break compatibility, which makes it a non-starter. It also becomes dubious with variable numbers of parameters.

 Waldemar
# Yongxu Ren (9 years ago)

Jeremy, I think you were talking about are cases like this:

let add = (x,y,...z) => x+y+Math.max(z);

Since rested argument always has to be the last parameter, I guess this should’t be a big problem if we can interpret this case as:

//regular function and the rested argument are not curried by default
let add = (x,y) => function(...z){
	return x+y+Math.max(z);
};

As long as we express it consistently, this shouldn’t be a problem.

Also, I do not believe this will be a problem:

Too late, add(a) already returns a + undefined.

First, I do not think anyone will ever intended to write code like this,

Second, if someone accidentally returned a function instead of an object, or a different function, it should be very obvious and can be very easily debugged.

# Bob Myers (9 years ago)

It's trivially simply to write a function currify which essentially does what your proprosed curry keyword does.

function currify(f) {
  return function _currify(flen, _f) {
    return (...args) => {
      var remaining = flen - args.length;
      return remaining <= 0 ?
        _f(...args) :
        _currify(remaining, (...args2) => _f(...args, ...args2));
    };
  }(f.length, f);
}


function add(a, b, c) { return a + b + c; }
var _add = currify(add);

console.log(_add(1)(2)(3));
console.log(_add(1, 2)(3));
console.log(_add(1)(2, 3));
console.log(_add(1, 2, 3));

-- Bob

# Isiah Meadows (9 years ago)

I also prefer explicit currying and partial application, since it's easier to reason about types. I would rather not deal with transparent, keyword-only currying, since it can eventually become hard to debug because it can get confusing as to how many parameters are left before application. It's especially the case with dynamically typed languages.

# Michał Wadas (9 years ago)

2015-10-15 22:20 GMT+02:00 Yongxu Ren <renyongxu at gmail.com>:

First, I do not think anyone will ever intended to write code like this,

It's a wrong assumption - tons of library code depends on some argument being null or undefined.

function ajax(url, options) { options = options || defaultOptions; ... }

And in user code it can be called:

ajax('menu.html'); ajax('menu.html', null); ajax('menu.html', undefined);

BTW - I think ES2016 needs some way to curry function without binding this. Function.prototype.curry or something like that.

# Isiah Meadows (9 years ago)

An npm package (not mine): npm.im/curry

Another simple implementation, ES3-compatible:

function curry(f) {
  function curried() {
    if (arguments.length >= f.length) {
      return f.apply(this, arguments);
    } else {
      var args = []
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      return function () {
        var rest = args.slice();
        for (var i = 0; i < arguments.length; i++) {
          rest.push(arguments[i]);
        }
        return curried.apply(this, rest);
      }
    }
  }
  Object.defineProperty(curried, "length",
    Object.getOwnPropertyDescriptor(f, "length"));
  return curried;
}

I don't need it often enough to want a standard library feature, but it's an easy function to make. And it does exactly what you want it to: curry a function without binding this. If you want to make it a method decorator as well, you can use this (also ES3-compatible):

function helper(f) {
  function curried() {
    if (arguments.length >= f.length) {
      return f.apply(this, arguments);
    } else {
      var args = []
      for (var i = 0; i < arguments.length; i++) {
        args.push(arguments[i]);
      }
      return function () {
        var rest = args.slice();
        for (var i = 0; i < arguments.length; i++) {
          rest.push(arguments[i]);
        }
        return curried.apply(this, rest);
      }
    }
  }
  Object.defineProperty(curried, "length",
    Object.getOwnPropertyDescriptor(f, "length"));
  return curried;
}

function curry(target, prop, desc) {
  if (typeof target === "function") {
    // called on function
    return helper(target);
  } else {
    // called as decorator
    desc.value = helper(desc.value);
  }
}
# Michał Wadas (9 years ago)

We can reverse this argument - why we needed Function.prototype.bind? It's quite easy to polyfill (especially if you have Reflect.construct for edge case of constructor or use eval for ES3/5 compatible implementation). There were hundreds libraries providing .bind.

Returning threads about partially applied function without writing boilerplate code or using external library are good argument to consider implementing it into language.

And in my opinion method is more readable than function.

# Yongxu Ren (9 years ago)

Michał, thanks for pointing that out. Yes, optional options as the last optional parameter does exist, in multiple libraries. But I is there really existed any library that using arrow function like this? I doubt it.

I think arrow function should only be used for lambda expression, callback and short in block function. It does cause incompatibility if anyone used arrow function for API interface, but doing that is anti-pattern.

Curry function are often used in iterations, a slow polyfill will defeat the purpose. Considering this case:

map (add 1) [1..100000]

I think native syntax support for curry will be a good thing, it can be used for JIT. However, javascript already too big, so why not just let existing syntax to do the work?

# Jeremy Darling (9 years ago)

Maybe it belongs on the Function prototype, something like Function.prototype.curry. To me, having Curry built into the language would be beneficial especially with the large push that is being seen toward Functional development in JavaScript.

# Isiah Meadows (9 years ago)

The main reason I don't use it is because I have bad experiences with transparent currying in dynamic languages. It'll be one of those things I almost never have the use case for. Kinda like SIMD and Math.imul. YMMV

# liorean (9 years ago)

Well, as I see it, there is nothing that currently could be done with to this if what you desire is to make it automatic. What we could add are various ways of manually doing this, either as syntax or as library extensions. And then comes the question of which way and what exactly.

Are you talking about pure currying, that is, taking a multiple parameter function and turning if into a series of it's arity many single argument functions, i.e: (a,b,c)=>a+b+c --> a=>b=>c=>a+b+c ?

Are you talking about partial application,i.e: (a,b,c)=>a+b+c --> (a,b,c..._)=>a+b+c

OR (a,b)=>(c,..._)=>a+b+c

OR a=>(b,c,..._)=>a+b+c

OR a=>b=>(c,..._)=>a+b+c

And where any zero argument applications return the same function?

Is it currying or partial application you want? How do you handle functions that take rest parameters, optional parameters, true variadric functions like e.g. sum that is theoretically zero to infinity arity? or whose arity with to partial application (and not the formal functionobject.length arity) is dependent on the contents of those arguments? How do you handle this value? How do you handle arguments object? How do you handle named autorecursion? Do you want to be able to do this for constructors as well? How about getters and setters? Generators? How do you handle extremely high argument counts? How do you handle defaults? How do you handle argumentless applications?

Automating this is in the language as it is would be a no-go for backwards compatibility reasons I would say. Possibly you could have manual currying, like what I wrote for rosettacode here: rosettacode.org/wiki/Currying#Generic_currying_for_ECMAScript_2015.28ES6.29

Note the several caveats in that code. And sure, you could add syntax for it instead of using a function like I do there, but it's still the same explicit action, so would syntax really help in any way? And for several cases you'd actually have to make a decision and stick to it, or implement all the alternatives. Just see how I had to deal with rest arguments there, because without two different versions, I would have to choose either to handle rest arguments always with a separate application, or never. If you want partial application, that's slightly different in a few ways, but not notably harder.

# Yongxu Ren (9 years ago)

How about we use a different approach?

Instead of allowing a(b)(c) for let a = (b,c) => b+c;,

Maybe we can use a(b,c) for let a = b => c => b + c?

# liorean (9 years ago)

On 17 Oct 2015 04:48, "Yongxu Ren" <renyongxu at gmail.com> wrote:

How about we use a different approach?

Instead of allowing a(b)(c) for let a = (b,c) => b+c;,

Maybe we can use a(b,c) for let a = b => c => b + c?

Would that do any of the useful stuff you could reasonably want either currying or partial application for, though? I mean the main use is that it allows us to do let d=a(b); ... d(c); And I don't really see how your desugaring a single multiple argument application into several single parameter curried functions allows that usefulness.

It's the multiple applications to fill single parameter list thing that is the most useful part of it, mostly as it allows caching the closure at any step for reuse, not single application to fill multiple sequential single parameter lists. Also, consider rest parameters, defaults etc. and whether doing what you want for the simple example case would have weird or possibly ambiguous meaning. Also, what happens to this value if the functions are old style and not new style?

# Isiah Meadows (9 years ago)

Here's what I see as what's being proposed here. Correct me if I'm wrong.

Function currying means it can be partially applied when only given some of its arguments. For example:

var add = _.curry(function (a, b, c) { return a + b + c })

add(1)(2)(3) === 6
add(1, 2)(3) === 6
add(1)(2, 3) === 6
add(1, 2, 3) === 6

var add3 = add(3)

add3(2, 1) === 6
add3(2)(1) === 6

var add5 = add(3, 2)

add5(1) === 6

That's exactly the behavior in Underscore's and Lodash's _.curry(). And that's exactly what I (and most others) would expect.


As for Yongxu Ren's idea, that wouldn't be very performant, as engines have never been made to handle very highly nested closures very well. That's a great idea in statically typed, mostly pure functional languages (Haskell and OCaml both do that), but in languages that accept multiple arguments for a single function like Java or Python, it's hard to optimize at all. JavaScript is no exception. It's also cheaper to do a function length comparison than an unavoidable IsCallable check for each argument passed (which that would require).

# Yongxu Ren (9 years ago)

As long as the total numbers of argument and types are consistent, which are mostly true for curry functions, it should be able to easily optimized.

Also, the polyfill for curry is just way too slow.

# Bob Myers (9 years ago)

Of course, faster is always better, and native is always (?) faster.

Having said that, with the fastest polyfill I have managed to write, given

function add(a, b, c) { return a + b + c; }
var _add = currify(add);

A call to add(1,2,3) takes 0.016 microseconds. A call to _add(1)(2)(3) takes 0.43 microseconds, 25 times longer. However, in the real world, it is more common to curry the function once and then invoke the curried function multiple times. If we do add1 = _add(1), then each call to add1(2)(3) takes 0.30 microseconds, or 20 times longer. If we do add2=_add(1, 2), then each call to add2(3) takes 0.10 microseconds, or 6 times longer. In relative terms this still seems like a large penalty, but in absolute terms, maybe not so much.

On another topic, in terms of the approach for delivering this functionality, the best solution would seem to be to put this in a new standard library. If we want to instead extend the language syntax, of course we cannot introduce a new curry keyword, but maybe we can take a hint from the * used for generators and do something like

function #add(a, b, c) { }
function :add(a, b, c) { }
function ()add(a, b, c) { }
function add((a, b, c)) { }

etc. etc.

-- Bob

# Hemanth H.M (9 years ago)

Something like curry-this would be nice to have, so we could do something like:

const add = (
    (a, b, c) => a + b + c
)::curry();