Chapter 12: Functional iteration
The chapter introduces map(), filter(), and reduce() as useful alternatives to for loops over arrays.
After this chapter you will be able to
- Functional tools for array loops. Explain why map(), filter(), and reduce() are useful in functional programs as alternatives to for loops over arrays.
- Implicit argument code smell. Describe how to spot an implicit argument in a function name: similar functions differ by a value named in the function and hard-coded in its body.
- Explicit argument refactoring. Explain how to express an implicit argument: add it as a parameter, use it instead of the hard-coded value, and update callers.
- Callback body refactoring. Describe how to replace a changing body with a callback while keeping the surrounding before-and-after code in a function.
- Map array transformation. Describe map() as a higher-order function that loops through an array and returns a new array of the same length, with the passed-in function determining each new value. Relate it to turning an array of customers into an array of emails.
- Shared iteration behind map. Explain how the functions share common array iteration while differing in the code that generates new elements, and describe how replacing that differing body with a callback produces map().
- Whole-array transformation with map. Explain how map() uses a function for one value to transform an entire array, producing an array of results.
- Calculation and action distinction. Distinguish what happens when the function passed to map() is a calculation versus an action.
- Ways to pass functions. Distinguish globally defined, locally defined, and inline functions by where they are defined, whether they have a name, and where that name can be used. Explain why a short, one-use function might be defined inline.
- Customer email transformation. Explain how map() turns an array of customers into an array of email addresses by applying a function to each customer.
- Subset selection versus mapping. Distinguish using map() to transform every customer from using filter() to keep only customers meeting a condition, such as three or more purchases.
- Filter selection callback. Explain how filter() captures common iteration while a callback supplies the test that determines which elements go into a new array.
- Filter predicate and result. Explain how filter() calls a predicate for each array element and uses its Boolean result to decide which elements appear in the new array.
- Customer selection with filter. Explain how filter() selects customers with zero purchases, and apply the same idea to separate customers into test and non-test groups by ID.
- Reduce iteration pattern. Explain how reduce() captures a common iteration pattern: start with an initial value, then calculate each next value from the previous value and the current array element.
- Reduce accumulation and callback. Explain how reduce() accumulates a value as it iterates over an array, and describe what the function passed to it receives and returns.
- String concatenation with reduce. Explain how reduce() can turn an array of strings into one concatenated string by combining the accumulated string with each current string.
- Initial value selection. Explain how to choose a reduce() initial value from where the calculation starts and what an empty array should produce.
- State from interaction history. Explain how reduce() can combine an initial state with a sequence of user interactions to reconstruct the current state or a state from an earlier point.
- Map and filter through reduce. Describe what the section establishes about implementing map() and filter() with reduce(), including why locally mutating the returned array can still yield a calculation.
- Three array iteration tools. Distinguish map(), filter(), and reduce() by describing how each uses an array and what it produces.
- Functional tools and iteration patterns. Explain that map(), filter(), and reduce() are commonly used, small functions that each do one thing well, and that they can be derived from familiar iteration patterns.
What it builds on
- Refactoring: Replace body with callback (chapter 10) · Introduces replacing a loop body with a callback.
- Code smell: Implicit argument in function name (chapter 10) · The earlier introduction of the implicit-argument code smell
- Refactoring: Express implicit argument (chapter 10) · The earlier treatment of expressing an implicit argument
- Implementing the coupon email process (chapter 3) · Introduced the coupon email process revisited here.
- Actions, calculations, and data (chapter 3) · Introduces the distinction between actions and calculations.
Section by section
Introduction
The chapter introduces map(), filter(), and reduce() as useful alternatives to for loops over arrays.
- Functional tools for array loops: Explain why map(), filter(), and reduce() are useful in functional programs as alternatives to for loops over arrays.
Why it matters: This gives you a reason to look for these tools when working with arrays.
Key terms: map(), filter(), reduce(), for loops, arrays
12.1 One code smell and two refactorings
The section reviews a code smell and two refactorings for turning hard-coded values and behavior into first-class arguments.
- Implicit argument code smell: Describe how to spot an implicit argument in a function name: similar functions differ by a value named in the function and hard-coded in its body.
Why it matters: Spotting the hidden argument reveals an opportunity to reduce duplication. - Explicit argument refactoring: Explain how to express an implicit argument: add it as a parameter, use it instead of the hard-coded value, and update callers.
Why it matters: Callers can supply the varying value rather than relying on separate hard-coded functions. - Callback body refactoring: Describe how to replace a changing body with a callback while keeping the surrounding before-and-after code in a function.
Why it matters: The shared surrounding code can be reused with different behavior supplied by callers.
Key terms: implicit argument in function name, code smell, express implicit argument, explicit argument, first-class, replace body with callback, before, body, and after, higher-order functions, first-class function
12.2 MegaMart is creating a communications team
MegaMart’s recurring customer-email requests motivate a brief introduction to map() as a way to transform an array.
- Customer communications code challenge: Explain why MegaMart’s new communications team expects to write many similar pieces of customer-data code: different emails must go to different subsets of more than a million customers.
Why it matters: The repeated requests explain why the team wants a clearer way to express array-processing code. - Map array transformation: Describe map() as a higher-order function that loops through an array and returns a new array of the same length, with the passed-in function determining each new value. Relate it to turning an array of customers into an array of emails.
Why it matters: This distinction shows how the customer-to-email transformation can be expressed without manually building the result array.
Key terms: subsets of customers, for loops, customer communications team, map(), forEach(), higher-order function, new array
12.3 Deriving map() from examples
The section derives map() by extracting a shared array-iteration pattern and making the code that generates each new element a callback.
- Shared iteration behind map: Explain how the functions share common array iteration while differing in the code that generates new elements, and describe how replacing that differing body with a callback produces map().
Why it matters: It shows how repeated iteration code becomes a reusable functional tool.
Key terms: map(), replace body with callback, before, body, and after, callback
12.4 Functional tool: map()
This section explains how map() applies a function to each array element and how the function passed to it affects whether the map() call is a calculation or an action.
- Whole-array transformation with map: Explain how map() uses a function for one value to transform an entire array, producing an array of results.
Why it matters: This lets you express a transformation for one item and use it on a whole array. - Calculation and action distinction: Distinguish what happens when the function passed to map() is a calculation versus an action.
Why it matters: Passing a function to map() does not hide whether that function performs an action. - Single-element callback naming: Describe why the example names its inline, anonymous function’s argument customer.
Why it matters: A singular argument name makes it easier to see what the function receives on each call.
Key terms: map(), array of X, array of Y, calculation, action, inline function, anonymous function, customer
12.5 Three ways to pass a function
This section explains three ways to define and pass functions in JavaScript: globally, locally, or inline.
- Ways to pass functions: Distinguish globally defined, locally defined, and inline functions by where they are defined, whether they have a name, and where that name can be used. Explain why a short, one-use function might be defined inline.
Why it matters: The choice determines whether a callback has a reusable name and which surrounding values it can refer to.
Key terms: globally defined, locally defined, inline function, anonymous function, local scope
12.6 Example: Email addresses of all customers
The section applies map() to customer data, warns that it preserves null results, and explains why selecting a subset calls for filter() instead.
- Customer email transformation: Explain how map() turns an array of customers into an array of email addresses by applying a function to each customer.
Why it matters: It helps you recognize when a whole-array transformation is a good fit for map(). - Null results in mapped arrays: Explain what happens if the function passed to map() returns null or undefined for a customer, and why this requires care.
Why it matters: Mapping an entire array can carry missing values into the result. - Subset selection versus mapping: Distinguish using map() to transform every customer from using filter() to keep only customers meeting a condition, such as three or more purchases.
Why it matters: The shape of the desired result tells you whether to transform every item or select some items.
Key terms: map(), Array of customers, null, undefined, filter(), subset, higher-order function
12.7 Deriving filter() from examples
The section derives filter() by extracting a shared array-iteration pattern and passing the element-selection test as a callback.
- Filter selection callback: Explain how filter() captures common iteration while a callback supplies the test that determines which elements go into a new array.
Why it matters: It lets you reuse the iteration while changing which elements are selected.
Key terms: filter(), test expression, callback, replace body with callback
12.8 Functional tool: filter()
This section explains how filter() uses a predicate to select elements from an array.
- Filter predicate and result: Explain how filter() calls a predicate for each array element and uses its Boolean result to decide which elements appear in the new array.
Why it matters: This lets you select matching elements without changing their order.
Key terms: filter(), predicate, Boolean
12.9 Example: Customers with zero purchases
The section applies filter() to select customers, shows how filtering can remove nulls from mapped results, and introduces reduce() for accumulating a value.
- Customer selection with filter: Explain how filter() selects customers with zero purchases, and apply the same idea to separate customers into test and non-test groups by ID.
Why it matters: A condition that tests one customer can select the whole group you need. - Removing nulls after mapping: Explain how filter() can remove null values left in an array by map().
Why it matters: Filtering lets you keep useful mapped results without keeping unwanted null entries. - Accumulating totals with reduce: Distinguish the purchase-count request from map() and filter() examples, and describe the accumulating role introduced for reduce().
Why it matters: Recognizing an accumulating result helps you choose the appropriate functional tool.
Key terms: filter(), subset, customer.id, remainder operator, map(), nulls, reduce(), accumulate, previous total, higher-order function
12.10 Deriving reduce() from examples
The section derives reduce() by identifying the common iteration in examples that repeatedly combine an accumulated value with an array element.
- Reduce iteration pattern: Explain how reduce() captures a common iteration pattern: start with an initial value, then calculate each next value from the previous value and the current array element.
Why it matters: This pattern lets you recognize when different loops can use the same iteration tool.
Key terms: reduce(), initialization, combining operation, current element
12.11 Functional tool: reduce()
This section explains how reduce() accumulates a value across an array using a function supplied by the caller.
- Reduce accumulation and callback: Explain how reduce() accumulates a value as it iterates over an array, and describe what the function passed to it receives and returns.
Why it matters: This explains why the same tool can perform different kinds of accumulation.
Key terms: reduce(), accumulator, current element, functional tools
12.12 Example: Concatenating strings
Uses string concatenation to show how reduce() combines an array, then explains argument order, initial values, and boundary cases for functional tools.
- String concatenation with reduce: Explain how reduce() can turn an array of strings into one concatenated string by combining the accumulated string with each current string.
Why it matters: It gives you a concrete way to recognize when reduce() fits a task. - Initial value selection: Explain how to choose a reduce() initial value from where the calculation starts and what an empty array should produce.
Why it matters: The initial value determines both where the combination begins and the result for an empty array. - Functional tool argument order: State the argument-order convention used in this book’s array functions, including where reduce() places its initial value.
Why it matters: Keeping the book’s convention straight helps avoid mixing up reduce()’s arguments. - Empty and identity cases: Describe the results the section gives for map(), filter(), and reduce() when arrays are empty or callbacks return their inputs or constant booleans.
Why it matters: These boundary cases make the tools’ behavior easier to predict.
Key terms: reduce(), accumulated string, current string, initial value, empty array, business rule, argument order, array first, function last, map()
12.13 Things you can do with reduce()
The section shows how reduce() can reconstruct state from a history of interactions and how it can express map() and filter(), including implementations that mutate only local values.
- State from interaction history: Explain how reduce() can combine an initial state with a sequence of user interactions to reconstruct the current state or a state from an earlier point.
Why it matters: A history of interactions can tell you both the current state and how the system reached it. - Map and filter through reduce: Describe what the section establishes about implementing map() and filter() with reduce(), including why locally mutating the returned array can still yield a calculation.
Why it matters: This example shows how to judge a local mutation by its effect on the function, rather than applying a guideline without context.
Key terms: reduce(), initial value, user interactions, current state, audit trails, map(), filter(), calculations, local value
12.14 Three functional tools compared
This section compares map(), filter(), and reduce() by what each does with an array.
- Three array iteration tools: Distinguish map(), filter(), and reduce() by describing how each uses an array and what it produces.
Why it matters: The distinction helps you choose a tool based on the result you want from an array.
Key terms: map(), filter(), reduce()
12.15 Conclusion
The conclusion connects map(), filter(), and reduce() to common iteration patterns and the functional-programming practice of using small, focused abstractions.
- Functional tools and iteration patterns: Explain that map(), filter(), and reduce() are commonly used, small functions that each do one thing well, and that they can be derived from familiar iteration patterns.
Why it matters: It helps you recognize familiar iteration patterns as opportunities for a focused functional tool.
Key terms: map(), filter(), reduce(), functional tools, iteration patterns
12.16 Summary
12.17 Up next…
Previews the next chapter’s use of chained functional tools to answer more complex questions about customer data.
Where this is used later
- Refactoring existing for loops to functional tools (chapter 13) · Refactors existing for loops to functional tools.
- Making the field name explicit (chapter 14) · Making a field name explicit applies the same idea of passing a varying value.
- Clarifying chains, method 2: Naming the callbacks (chapter 13) · Naming callbacks draws on the distinction between named functions and functions defined where they are used.
- Example: Emails of customers who have made one purchase (chapter 13) · Combines customer selection with extracting email addresses.
- The customer communications team continues (chapter 13) · Introduces reduce() as a functional tool.
- (chapter intro) (chapter 13) · Assumes familiarity with individual functional tools for working with arrays.
- Summary of chaining tips (chapter 13) · The different roles of map(), filter(), and reduce()
- Many other functional tools (chapter 13) · The distinct roles of map(), filter(), and reduce()
Concepts explained in this chapter
- higher-order functionA function that accepts functions as arguments, returns functions as results, or otherwise treats functions as values.
- accumulatorA function passed to a reduction operation that combines the accumulated result with the current sequence element.
- inline functionA function defined at the place in a program where it is used rather than assigned to a separate name.
- lambdaA function expression that has no name and can be defined inline where it is used.
- extract function argument refactoringA refactoring technique that converts information encoded implicitly in a function name or surrounding code into an explicit function argument.
- implicit argumentA code smell in which a function's name encodes a value that would more appropriately be supplied explicitly as an argument.
- replace body with callbackA refactoring technique that extracts unchanged before-and-after code into a function and supplies the varying body as a callback argument.
- scopeThe region of a program in which a binding can be accessed or referenced.
These guides are generated from the text of Manning books by Manning's knowledge graph and link to the sections they draw on. The full books are available on liveBook and at manning.com.
