liveBook · Manning

Currying

As explained in The Joy of JavaScript

A technique that transforms a function of multiple arguments into a sequence of functions each taking a single argument.

Currying turns a function of multiple arguments into a sequence of functions that accept arguments one at a time. Each call supplies part of the input and returns a function for the next part; the final call produces the result. This makes a function easier to configure before placing it in a composition chain. section 4.4.1 section 4.4

Supply one argument now, another later

const add = x => y => x + y; const addThreeTo = add(3); addThreeTo(7); // 10 The first call retains 3 in a closure. The returned function can be called later—or passed elsewhere—with the remaining argument. section 4.4.1 section 4.4

That retained value is useful for configuration. For example, `const decode = (encoding = 'utf8') => buffer => buffer.toString(encoding)` lets `decode('utf8')` act as a one-input step in a file-processing composition. Configuration is visible where the chain is assembled, while the buffer arrives when the chain runs. Keep closures narrow and avoid observable changes to surrounding state. section 4.4.1 section 4.4

Common uses and tradeoffs:

  • Adapt a multi-argument function to composition: `computeCipher(options)` leaves a function that accepts assembled data, rather than mistakenly treating that data as the options argument. section 4.4.2
  • Put the changing input last: `const map = curry((f, arr) => arr.map(f))` allows `map(balanceOf(address))` to wait for an array supplied by `compose`. section 4.7
  • Use a `curry` helper to avoid writing nested functions repeatedly, but check how it determines arity: JavaScript reports `length` as 0 for a function whose parameters both have defaults. section 4.4.1
Listing 4.12 Final implementation of HasHash
const HasHash = (
  keys,
  options = { 
       algorithm: 'SHA256', 
       encoding:  'hex' 
    }
) => ({
  calculateHash() {
     return compose(
      computeCipher(options),
      assemble,
      props(keys)
    )(this);           #1
  }
});

The hashing pipeline configures property selection and cipher options first, then passes the object through the resulting functions. Currying lets each stage accept the preceding stage’s output. section 4.4.2

Curried standalone functions also support composition with utilities such as Ramda’s `map` and `flatMap`. Currying arranges when arguments arrive; it does not itself make a function pure. Predictable pipelines still depend on the behavior of the functions being combined. section 5.5.8 section 4.4.2

How The Joy of JavaScript covers it

How deep it goes
Defines stepwise application, works through manual and helper-based currying, and flags an arity caveat; reviews closures without treating them in depth.
Examples
Uses nested addition, configurable buffer decoding, property access, object hashing, and curried array mapping.
What it assumes
Assumes familiarity with JavaScript functions and composition, while briefly reviewing the closures that retain supplied arguments.
What you can do after
Build it from scratch with nested functions or a curry helper, then configure functions for composition.
How it connects
Connects currying to closures, higher-order functions, function composition, partial configuration, pure functions, and point-free style.

Also explained in

Compare how 7 books explain currying →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.