Working with map, filter, fold, and apply

Choose map to transform elements, filter to select them, and a fold to combine them into one result.

Use filter to keep selected elements, map to change each element, and a fold to combine them into one result. This example adds the squares of the odd numbers in a list.

Select, transform, and add

Run this complete example in the Playground.

LISPEX
(reduce + 0 (map (lambda (x) (* x x)) (filter odd? (list 1 2 3 4))))

Result

OUTPUT
10

Read the nested calls from the inside out.

  1. filter keeps 1 and 3, the elements for which odd? returns #t.
  2. map squares those elements and produces (1 9).
  3. reduce starts with 0 and adds the squares to get 10.

Each of these procedures receives another procedure as an argument. That makes it a higher-order procedure. The procedure it calls for each element is often called a callback.

Choose by the result you need

Your taskProcedure
Produce one transformed element for each input elementmap; use string-map or vector-map for strings or vectors
Keep elements that pass a testfilter
Combine elements into one accumulated resultreduce or its alias fold-left; use fold-right to start from the right
Ask whether all or any elements pass a testall? or any?; they stop as soon as the answer is known
Perform an action such as printing each elementfor-each, string-for-each, or vector-for-each

The traversal procedures take one list, string, or vector. The reference gives the arguments and return values for each call.

Pass a list of arguments with apply

Use apply to call a procedure once with arguments stored in a list.

LISPEX
(apply + 1 (list 2 3))

Result

OUTPUT
6

This calls + with 1, 2, and 3. The elements of the final list follow any arguments supplied before it.

Find what to fix

An E302 error means an argument count is wrong. Check both the outer call and the procedure passed to it. For example, map passes one element at a time, while reduce passes an accumulator and an element.

An E320 error means a call produced zero or multiple values where one was needed. If you used map with display, use for-each for printing. If you need a new list, make the procedure passed to map return one value per element.

The higher-order reference lists these requirements together so you can check the failing call.

Try a change

Replace odd? with even? in the first example. What does it return?

Answer

It keeps 2 and 4, squares them to (4 16), and returns 20.

Use recursion when you need to control the traversal yourself.