this section outlines the main choices when designing loops. recursion, iteration, and higher-order forms like map or fold are interchangeable; the key is understanding when and how to use each based on termination, state, and structure.
each loop construct can be analyzed along the following axes:
termination: how and when the loop stops
state management: what data is updated across iterations
composition style: how the loop integrates with surrounding code
control flow abstraction: how much of the control is abstracted
full control: explicit loop or recursion
partial abstraction: fold, unfold, etc.
total abstraction: lazy sequences, generators
map: applies a function to each element and returns a new structure
fold/reduce: accumulates a result by applying a function across elements
unfold: generates a structure from a seed by repeated transformation
custom recursive loop: uses a named recursive binding (e.g. let loop)
full control over state and branching
allows multiple outputs and mixed control flows
in scheme
(let loop ((rest (list 1 2 3)))
(if (null? rest) rest
(cons (+ 1 (car rest)) (loop (cdr rest)))))this implements a basic map operation by:
(null? rest)loop with (cdr rest)cons and (+ 1 ...)this style generalizes easily - for example, by accumulating additional values, branching conditionally, or logging state.
identify the stop condition early
determine what state changes per iteration
decide how much abstraction is acceptable
map, foldlet loopconsider composition