# Iteration Cheat Sheet#

## Simple iteration with `while` and `until`#

```while (condition?)
// do something while the test condition? is true
end;
```
```until (condition?)
// do something until the test condition? is true
end;
```

Read more in the DRM: `while` and `until`.

## The `for` loop#

The `for` loop can be used in many different ways. We demonstrate some of the most commonly used features here:

### Iterating over a collection#

```for (element in collection)
// do something with element
end;
```

### Iterating over a range#

```for (count from 0 below num)
// do work
// count ranges from 0 to the integer below num
end;

for (column from 1 to 3)
// do work
// count ranges from 1 to 3, inclusive.
end;

// Changing the stepping and going in reverse
for (index from stop - 1 to start by -1)
// index will start at 'stop - 1' and end at the
// value of 'start', decrementing by 1 with each
// iteration of the loop.
end;
```

### Iterating over a table#

The easiest way to iterate over a table is to use an extension to the standard `for` loop that Open Dylan supports:

```for (value keyed-by key in table)
// do work
end;
```

If you want to directly access the keys of the table, you can use `key-sequence`:

```for (key in table.key-sequence)
// do work
end;
```

## Breaking out of a loop#

Breaking out of a loop is just like any other non-local exit in Dylan. Combine any loop with a `block` expression:

```let result = block (exit-block)
while (~done())
if (got-error?())
exit-block(1);
end;
end;
2
end;
```

In the example, if the loop ends naturally because `done()` returns true, then the result is `2` because the `while` exits naturally and `2` is the last expression in the block. If `got-error?` returns true, the result is `1` because that was the value passed to `exit-block`.

## Collection Functions#

When working with a collection, some additional operations are available that remove the need for explicit iteration over the collection.

In all of these, the function passed in can be any of:

### `do`#

`do` iterates over one or more collections, performing side effects:

```do(method (x)
format-out("%s\n", x)
end,
#[1, 2, 3])
```

### `map`, `map-as`, `map-into`#

`map` iterates over one or more collections, applying a function and returns the results in a new collection. `map-as` and `map-into` allow control over the way that the results are returned.

```let type-bindings = map(generate-type-binding, all-var-specs);
```
```let strings = map(curry(as, <string>), names);
```
```let c-direct-superclasses = map-as(<list>, convert, direct-superclasses(c));
```

Read more in the DRM: `map`, `map-as`, `map-into`.

### `reduce`, `reduce1`#

`reduce` combines the elements of a collection and a seed value into a single value by repeatedly applying a binary function.

`reduce1` is similar to `reduce`, except that the first value of the collection is used as the seed value.

```reduce(\*, 1, dimensions(x))
```
```reduce1(\+, #(1, 2, 3, 4, 5))
```

`reduce` is often combined with `map` operations:

```reduce(\+, 0, map(size, qqs))
```

## Iteration with Tail Recursion#

The `iterate` macro in the `common-dylan` library is another powerful way to do iteration. It relies on the fact that Dylan implementations are required to optimize tail recursion.

```let x = 7;
let factorial = iterate loop (n = x, total = 1)
if (n < 2)
total
else
loop(n - 1, n * total)   // tail call = iteration
end
end;
```

Here `iterate` creates a local method, `loop`, with two parameters `n` and `total` which calls itself recursively until `n < 2` is true and then it returns the value of `total`. It then calls the method with the parameter default values, `x` and `1`.

You could of course do the same thing with a local method yourself but the `iterate` macro makes it more concise.