Next: , Up: Gathering Clauses


2.3.1 Reductions

Reduction is an extremely common iteration pattern in which the results of successive applications of a binary operation are accumulated. For example, a loop that computes the sum of the elements of a list is performing a reduction with the addition operation. This could be written in Common Lisp as (reduce #'+ list) or with iterate as

  (iter (for el in list)
        (sum el))

— Clause: sum expr &optional into var

Each time through the loop, expr is evaluated and added to a variable, which is bound initially to zero. If expr has a type, it is not used as the type of the sum variable, which is always number. To get the result variable to be of a more specific type, use an explicit variable, as in

       (iter (for el in number-list)
             (sum el into x)
             (declare (fixnum x))
             (finally (return x)))
  

— Clause: multiply expr &optional into var

Like sum, but the initial value of the result variable is 1, and the variable is updated by multiplying expr into it.

— Clause: counting expr &optional into var

expr is evaluated on each iteration. If it is non-nil, the accumulation variable, initially zero, is incremented.

— Clause: maximize expr &optional into var
— Clause: minimize expr &optional into var

expr is evaluated on each iteration and its extremum (maximum or minimum) is stored in the accumulation variable. If expr is never evaluated, then the result is nil (if the accumulation variable is untyped) or 0 (if it has a numeric type).

— Clause: reducing expr by func &optional

initial-value init-val into var

This is a general way to perform reductions. func should be a function of two arguments, the first of which will be the value computed so far and the second of which will be the value of expr. It should return the new value. reducing is roughly equivalent to the Common Lisp (reduce func sequence :key expr-function), where expr-function is used to derive values from the successive elements of sequence.

If the reducing clause is never executed, the result is undefined.

It is not necessary to provide an initial value, but better code can be generated if one is supplied. Regardless of its location in the iterate body, init-val will be evaluated before the loop is entered, so it should not depend on any value computed inside the iterate form.