Why Lodash/fp Functions Are Auto-Curried by Default
Lodash's functional programming variant, lodash/fp,
automatically curries its functions to promote clean functional
composition, enable effortless partial application, and reduce
boilerplate in data transformation pipelines. By transforming
multi-argument utilities into sequences of single-argument functions,
lodash/fp allows developers to configure transformations
upfront and apply them to data later, aligning standard JavaScript with
modern functional programming paradigms.
Understanding Auto-Currying
Currying is the process of converting a function that takes multiple
arguments into a chain of functions that each take a single argument. In
standard Lodash, calling _.map(collection, iteratee)
requires both the data and the operation to be supplied together. In
lodash/fp, calling fp.map(iteratee) without
the second argument does not throw an error or return
undefined; instead, it returns a new function waiting to
receive the collection.
The Synergy Between Currying and "Data-Last" Arguments
Standard Lodash is "data-first"
(_.filter(array, predicate)), which is optimal for method
chaining via object wrappers. However, lodash/fp flips this
convention to "iteratee-first, data-last"
(fp.filter(predicate, array)).
Auto-currying is designed to leverage this rearranged argument order. Because the data argument is always placed last, omitting it automatically generates a reusable transformer function that awaits the data:
// Pre-configured, reusable utility
const getActiveUsers = fp.filter(user => user.isActive);
// Applied later to various datasets
const activeAdmins = getActiveUsers(adminList);
const activeMembers = getActiveUsers(memberList);Facilitating Function Composition and Pipelines
Modern functional code relies heavily on composition mechanisms like
fp.flow or fp.compose (left-to-right or
right-to-left execution). These utilities pass the return value of one
function directly into the next as an argument.
Without auto-currying, combining Lodash methods requires verbose arrow function wrappers:
// Without auto-currying:
const getAdultNames = data =>
fp.flow(
d => fp.filter(user => user.age >= 18, d),
d => fp.map(user => user.name, d)
)(data);With auto-curried functions, the explicit argument references disappear:
// With auto-currying:
const getAdultNames = fp.flow(
fp.filter(user => user.age >= 18),
fp.map('name')
);Enabling "Point-Free" Style
Auto-currying enables point-free (tacit) programming, a paradigm where function definitions do not explicitly identify the arguments (or "points") they process. By removing the need to name intermediary variables that merely pass data from one step to the next, codebase noise decreases, cognitive load is reduced, and individual operations become easier to test, isolate, and reuse across an application.