# `for` Loops

### `for` Loops

A `for` loop visits the elements of an array, slice, or range.

```zig
const std = @import("std");

pub fn main() void {
    const data = [_]u8{ 10, 20, 30 };

    for (data) |x| {
        std.debug.print("{d}\n", .{x});
    }
}
```

The output is:

```text
10
20
30
```

The name between bars is the loop capture.

```zig
|x|
```

On each iteration, `x` is the current element.

A `for` loop over an array visits each element in order.

```zig
const letters = [_]u8{ 'a', 'b', 'c' };

for (letters) |ch| {
    std.debug.print("{c}\n", .{ch});
}
```

A string literal is an array of bytes, so a loop over a string visits bytes.

```zig
for ("zig") |b| {
    std.debug.print("{c}\n", .{b});
}
```

This prints:

```text
z
i
g
```

This is byte iteration. It is not Unicode character iteration. A UTF-8 character may use more than one byte.

A `for` loop can also capture the index.

```zig
const data = [_]u8{ 10, 20, 30 };

for (data, 0..) |x, i| {
    std.debug.print("{d}: {d}\n", .{ i, x });
}
```

The output is:

```text
0: 10
1: 20
2: 30
```

The expression `0..` is an open-ended range. In this loop, Zig pairs it with `data`, so it gives the indices `0`, `1`, and `2`.

A closed range has both ends.

```zig
for (0..5) |i| {
    std.debug.print("{d}\n", .{i});
}
```

This prints:

```text
0
1
2
3
4
```

The end is not included.

A `for` loop can iterate over more than one sequence at the same time.

```zig
const names = [_][]const u8{ "red", "green", "blue" };
const values = [_]u8{ 1, 2, 3 };

for (names, values) |name, value| {
    std.debug.print("{s}: {d}\n", .{ name, value });
}
```

All sequences must have the same length, unless one of them is an open-ended range used for indexing.

Use a pointer capture to modify elements.

```zig
var data = [_]u8{ 1, 2, 3 };

for (&data) |*x| {
    x.* += 1;
}
```

After the loop, `data` is:

```zig
[_]u8{ 2, 3, 4 }
```

The `&data` passes a pointer to the array. The capture `|*x|` captures a pointer to each element. The expression `x.*` means the value pointed to by `x`.

Without pointer capture, the loop gets a copy of each element.

```zig
var data = [_]u8{ 1, 2, 3 };

for (data) |x| {
    _ = x + 1;
}
```

This does not change `data`.

Use `break` to leave a `for` loop.

```zig
const data = [_]u8{ 5, 8, 13, 21 };

for (data) |x| {
    if (x == 13) break;
    std.debug.print("{d}\n", .{x});
}
```

This prints:

```text
5
8
```

Use `continue` to skip one iteration.

```zig
const data = [_]u8{ 1, 2, 3, 4, 5 };

for (data) |x| {
    if (x % 2 == 0) continue;
    std.debug.print("{d}\n", .{x});
}
```

This prints:

```text
1
3
5
```

Like `while`, a `for` loop may have an `else` branch. The `else` branch runs only if the loop finishes normally.

```zig
const data = [_]u8{ 1, 2, 3 };

for (data) |x| {
    if (x == 9) break;
} else {
    std.debug.print("not found\n", .{});
}
```

The loop does not break, so the `else` branch runs.

A `for` loop can produce a value.

```zig
const data = [_]u8{ 4, 7, 9, 12 };

const found = for (data, 0..) |x, i| {
    if (x == 9) break i;
} else null;
```

The value of `found` is `2`. If no element equals `9`, the value is `null`.

This is a compact search pattern.

```zig
const index = for (data, 0..) |x, i| {
    if (x == target) break i;
} else null;
```

The type of `index` is `?usize`.

Use `for` when the number of iterations comes from the data. Use `while` when the loop is controlled by a condition that changes in a less regular way.

```zig
for (items) |item| {
    use(item);
}
```

This says: visit every item.

```zig
while (readNext()) |item| {
    use(item);
}
```

This says: keep going while another item can be read.

Exercise 3-17. Write a `for` loop that prints every element in an array.

Exercise 3-18. Print each element with its index.

Exercise 3-19. Use pointer capture to double every number in an array.

Exercise 3-20. Write a `for` expression that returns the index of the first even number, or `null` if there is none.

