How Lodash/fp Changes Lodash Argument Order

The lodash/fp module promotes a functional programming style by modifying the default behavior of the standard Lodash library. Its most significant adjustment is rearranging function parameters from a "data-first" convention to a "data-last" convention, alongside making functions auto-curried by default. This guide explains why and how lodash/fp restructures these argument orders to facilitate function composition and cleaner JavaScript code.

The Core Shift: Data-First vs. Data-Last

Standard Lodash follows a data-first approach. In standard Lodash methods, the target data structure (such as an array or an object) is always supplied as the first argument, followed by configuration parameters such as iteratee callbacks, property paths, or transformation criteria.

In contrast, lodash/fp inverts this pattern into a data-last approach. The operation rules, predicates, or paths come first, while the actual data being operated on comes last.

Standard Lodash (Data-First)

import _ from 'lodash';

// Signature: _.map(collection, iteratee)
const numbers = [1, 2, 3];
const doubled = _.map(numbers, (n) => n * 2);

// Signature: _.get(object, path, defaultValue)
const user = { profile: { name: 'Alice' } };
const name = _.get(user, 'profile.name', 'Default');

Lodash/fp (Data-Last)

import fp from 'lodash/fp';

// Signature: fp.map(iteratee, collection)
const numbers = [1, 2, 3];
const doubled = fp.map((n) => n * 2, numbers);

// Signature: fp.get(path, object)
const user = { profile: { name: 'Alice' } };
const name = fp.get('profile.name', user);

Why Argument Order is Altered

The primary purpose of the data-last design is to enable partial application and point-free function composition. Because all functions in lodash/fp are automatically curried, omitting the final data argument returns a new function awaiting that data.

This design makes it seamless to build processing pipelines using utilities like fp.pipe or fp.compose:

import fp from 'lodash/fp';

const processUsers = fp.pipe([
  fp.filter((user) => user.isActive),
  fp.map((user) => user.score),
  fp.sortBy((score) => -score)
]);

// The data enters only at the final execution step
const activeScores = processUsers(usersList);

If the collection were the first argument, currying would bind the data immediately, preventing the creation of reusable transform functions.

Iteratee Argument Capping

Along with reordering arguments, lodash/fp changes the arguments passed to iteratee callbacks.

Standard Lodash typically passes multiple arguments to iteratee callbacks (for instance, (value, index/key, collection) in _.map). In lodash/fp, iteratees are capped to a single argument (value) by default. This avoids unintended side effects when combining curried methods with built-in JavaScript functions (such as parseInt), which might misinterpret index parameters as numerical radix values.