Operator for Currying

# Vikash Agrawal (6 years ago)

I was going through the archives and found that some time ago, there had been discussions around currying [ esdiscuss.org/topic/curried-functions] and wanted to know if there was any proposal for the same or how did the discussion go?

I feel as we are proceeding with |> the pipeline operator, we should also

discuss the potential of a currying operator and find out if this would be helpful.

~Vikash

# Isiah Meadows (6 years ago)

Look here: tc39/proposal-pipeline-operator/#related-proposals One of the links points to a partial application operator, and alternative proposals in that repo are being actively discussed which don't require partial application. So similar stuff have already been considered, and currying has come up more than once.

My personal argument for curried functions in the spec is that 1. it's generally useful in many contexts, and 2. the engine can better optimize the hell out of it, not having to enter a full function + code context just to return a lightweight closure. (For similar reasons, I've in the past railed engines, in particular V8, for not properly optimizing Function.prototype.bind. The call sequence is brain-dead easy to optimize, and there's no good reason for it to be slower than a function expression.)

Isiah Meadows me at isiahmeadows.com

Looking for web consulting? Or a new website? Send me an email and we can get started. www.isiahmeadows.com

# Tab Atkins Jr. (6 years ago)

While I love currying in many languages, I have some reservations about it being generally useful enough in JS to be worth adding syntax for.

  1. Currying isn't friendly with variadic functions (that is, optional arguments) - you can't tell when the function has consumed "enough" arguments to finally resolve itself unless you predefine the arity.
  2. Currying isn't friendly with JS's style of named arguments (passing an option bag) - no clue how to solve this even with workarounds?

Partial application, whether via a dedicated syntax or as part of the smart-mix pipeline syntax, gives you most of the benefits of currying while solving these issues: 1, the partially-evaluated function will fully evaluate as soon as you call it, with whatever arguments you've given it (unless you explicitly partially-evaluate again); 2, with object-rest, you can spread a later options object into your partially-filled in options object, and then pass that to the underlying function.

// variadic example with pipeline function
const threeOrMore = +> Math.max(3, ...);
// and you can partially-eval again to fill in more options without "finishing":
const moreLimitations = +> threeOrMore(newLimit, ...);`

// option-bag example with arrow function
const someOptions = (arg, moreOpts) => optUsingFunction(arg, 1, 2,
{foo: bar, ...moreOpts});
// or with pipeline function:
const someOptions = +> optUsingFunction(#, 1, 2, {foo:bar, ...##});
# Isiah Meadows (6 years ago)

I do agree with much of your sentiment. I do have a few points inline, though:


Isiah Meadows me at isiahmeadows.com

Looking for web consulting? Or a new website? Send me an email and we can get started. www.isiahmeadows.com

On Thu, Mar 22, 2018 at 6:43 PM, Tab Atkins Jr. <jackalmage at gmail.com> wrote:

While I love currying in many languages, I have some reservations about it being generally useful enough in JS to be worth adding syntax for.

Understandable, and my biggest reason for not is because it doesn't mix well with function declarations.

  1. Currying isn't friendly with variadic functions (that is, optional arguments) - you can't tell when the function has consumed "enough" arguments to finally resolve itself unless you predefine the arity.

The typical method of handling this is to predefine the arity somehow, either via argument or checking func.length. In fact, most of Ramda's variadic functions have their length set to something useful (usually 1 or 2), and most other functional libraries do similar.

  1. Currying isn't friendly with JS's style of named arguments (passing an option bag) - no clue how to solve this even with workarounds?

OCaml has named arguments, both required and optional. They are really the only way you can pass "optional" arguments in the usual sense, and they don't support currying. You can still "partially apply" them by using an anonymous function (OCaml doesn't have any way of partial application).

Partial application, whether via a dedicated syntax or as part of the smart-mix pipeline syntax, gives you most of the benefits of currying while solving these issues: 1, the partially-evaluated function will fully evaluate as soon as you call it, with whatever arguments you've given it (unless you explicitly partially-evaluate again); 2, with object-rest, you can spread a later options object into your partially-filled in options object, and then pass that to the underlying function.

// variadic example with pipeline function
const threeOrMore = +> Math.max(3, ...);
// and you can partially-eval again to fill in more options without "finishing":
const moreLimitations = +> threeOrMore(newLimit, ...);`

// option-bag example with arrow function
const someOptions = (arg, moreOpts) => optUsingFunction(arg, 1, 2,
{foo: bar, ...moreOpts});
// or with pipeline function:
const someOptions = +> optUsingFunction(#, 1, 2, {foo:bar, ...##});

I agree that for most cases, it's better to use partial application instead of currying. To be quite honest, I feel automatic currying to be an easy code maintenance footgun. Clojure has no native support for it, OCaml idiomatically rarely uses it (short of the |> operator),

and even Haskell users try to limit it to high-context situations where the currying just removes noise (they often call point-free/tacit style "pointless").