Using Lodash flow to Compose Functions Left to Right
This article explains how the _.flow method in the
Lodash JavaScript library creates a function pipeline through
left-to-right composition. You will learn the mechanics behind how
arguments are passed between composed functions, see practical code
demonstrations, and understand how to implement the underlying logic
using native JavaScript.
Understanding _.flow
In functional programming, function composition is the process of
combining two or more functions to produce a new function. While
mathematical composition traditionally evaluates from right to left,
Lodash provides _.flow to evaluate functions in natural
reading order: from left to right.
The _.flow method takes an array of functions (or
functions supplied as individual arguments) and returns a new composite
function.
const _ = require('lodash');
const add = (x, y) => x + y;
const square = n => n * n;
const double = n => n * 2;
const transform = _.flow([add, square, double]);
transform(2, 3); // Output: 50How Evaluation Works Step-by-Step
When the composed function produced by _.flow is
invoked, the execution follows a strict sequence:
- Initial Invocation: The first function in the
pipeline can accept multiple arguments. In the example above,
add(2, 3)receives both inputs and evaluates to5. - Intermediate Handoff: The return value of the first
function is supplied as the sole argument to the second function. Here,
square(5)evaluates to25. - Pipeline Continuation: Each subsequent function
receives the resolved output of the function directly preceding it.
double(25)evaluates to50. - Final Output: The return value of the final function in the sequence becomes the return value of the entire composite function call.
Native JavaScript Equivalent
Under the hood, _.flow operates essentially like
Array.prototype.reduce. Understanding this implementation
demystifies the behavior:
const customFlow = (...funcs) => {
return (...initialArgs) => {
return funcs.slice(1).reduce((accumulator, currentFunc) => {
return currentFunc(accumulator);
}, funcs[0](...initialArgs));
};
};
const processNumber = customFlow(
(a, b) => a + b,
n => n * 3,
n => `Result: ${n}`
);
console.log(processNumber(4, 2)); // Output: "Result: 18"In this mechanism, the accumulator holds the intermediate result at each step, moving forward through the list of functions until the final result is calculated.
Practical Use Case: Data Transformation
Left-to-right composition is particularly useful for readable data sanitization and transformation pipelines:
const trim = str => str.trim();
const toLowerCase = str => str.toLowerCase();
const removePunctuation = str => str.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
const splitWords = str => str.split(" ");
const cleanAndTokenize = _.flow([
trim,
toLowerCase,
removePunctuation,
splitWords
]);
const tokens = cleanAndTokenize(" Hello, World! Welcome to Lodash. ");
// Result: ["hello", "world", "welcome", "to", "lodash"]Without _.flow, performing these operations requires
either nested function calls evaluated from the inside out
(splitWords(removePunctuation(toLowerCase(trim(text))))) or
storing intermediate values in temporary variables.
_.flow vs.
_.flowRight
Lodash also provides _.flowRight, which is an alias for
traditional mathematical composition (compose). The
distinction is purely directional:
_.flow: Executes from index0to indexn(Left-to-Right)._.flowRight: Executes from indexndown to index0(Right-to-Left).
For readability and consistency with standard data processing
pipelines, _.flow is preferred because its execution
matches standard top-to-bottom or left-to-right reading order.