# `for` Loops

### `for` Loops

A `while` loop repeats while a condition is true.

A `for` loop is different. It walks through items.

Use `for` when you already have a group of values and want to visit each one.

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

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

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

This prints:

```text
10
20
30
```

The array is:

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

The loop is:

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

Read it as:

for each item in `numbers`, call the current item `n`, then run the loop body.

#### The Basic Shape

The basic shape is:

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

The name between `|` and `|` is the loop capture.

```zig
|item|
```

That name refers to the current item.

You can choose a better name:

```zig
for (users) |user| {
    // use user
}

for (bytes) |byte| {
    // use byte
}

for (tokens) |token| {
    // use token
}
```

Good names make loops easier to read.

#### Looping Over an Array

An array has a fixed length known at compile time.

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

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

This prints:

```text
a
b
c
```

The format string uses `{c}` because each item is a character.

#### Looping Over a Slice

A slice is a view into a sequence of items.

```zig
const values = [_]u8{ 5, 6, 7, 8 };
const slice = values[1..3];

for (slice) |value| {
    std.debug.print("{}\n", .{value});
}
```

This prints:

```text
6
7
```

The slice:

```zig
values[1..3]
```

starts at index `1` and stops before index `3`.

So it contains:

```text
6, 7
```

`for` works naturally with slices. This is one of the most common loop patterns in Zig.

#### Looping Over a String

A string literal in Zig is a sequence of bytes.

```zig
const text = "abc";

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

This prints:

```text
a
b
c
```

This loops over bytes, not Unicode characters.

For plain ASCII text, each byte is one visible character. For UTF-8 text, one visible character may use more than one byte. We will study UTF-8 later. For now, remember this rule: `for` over a string gives bytes.

#### Getting the Index

Often you need both the item and its index.

Use a range beside the collection:

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

pub fn main() void {
    const names = [_][]const u8{ "ada", "zig", "c" };

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

This prints:

```text
0: ada
1: zig
2: c
```

The loop is:

```zig
for (names, 0..) |name, index| {
```

This means:

walk through `names`

also count upward starting from `0`

call the current item `name`

call the current index `index`

The order matters. The captures match the inputs.

```zig
for (names, 0..) |name, index| {
```

`name` comes from `names`.

`index` comes from `0..`.

#### Ranges

A range can be used by itself.

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

This prints:

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

The range:

```zig
0..5
```

starts at `0` and stops before `5`.

So it includes `0`, `1`, `2`, `3`, and `4`.

The end is exclusive.

#### Start Is Included, End Is Excluded

This is important:

```zig
0..5
```

means:

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

It does not include `5`.

This same rule appears in slice syntax:

```zig
items[0..5]
```

That means items at indexes `0`, `1`, `2`, `3`, and `4`.

The rule is consistent: start included, end excluded.

#### Modifying Items

By default, a `for` loop gives you each item as a value.

If you want to modify items, loop over pointers.

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

pub fn main() void {
    var numbers = [_]u8{ 1, 2, 3 };

    for (&numbers) |*n| {
        n.* += 10;
    }

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

This prints:

```text
11
12
13
```

The important line is:

```zig
for (&numbers) |*n| {
```

`&numbers` gives access to the array by reference.

`|*n|` captures a pointer to each item.

Inside the loop, `n` is a pointer. To read or write the pointed-to value, use:

```zig
n.*
```

So this:

```zig
n.* += 10;
```

means:

add `10` to the actual item inside the array.

#### Why `|*n|` Matters

This loop does not change the array:

```zig
for (numbers) |n| {
    var copy = n;
    copy += 10;
}
```

Here, `n` is a copy of each item. Changing a copy does not change the array.

This loop changes the array:

```zig
for (&numbers) |*n| {
    n.* += 10;
}
```

Here, `n` points to the actual item.

Use pointer capture only when you need mutation.

#### `continue` in a `for` Loop

`continue` skips the rest of the current loop body.

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

pub fn main() void {
    const numbers = [_]u8{ 1, 2, 3, 4, 5 };

    for (numbers) |n| {
        if (n % 2 == 0) {
            continue;
        }

        std.debug.print("{}\n", .{n});
    }
}
```

This prints:

```text
1
3
5
```

When `n` is even, the loop skips the print statement.

#### `break` in a `for` Loop

`break` exits the loop immediately.

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

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

    for (numbers) |n| {
        if (n == 30) {
            break;
        }

        std.debug.print("{}\n", .{n});
    }
}
```

This prints:

```text
10
20
```

When `n` becomes `30`, the loop stops.

#### `for` with `else`

A `for` loop can have an `else` branch.

The `else` branch runs if the loop finishes normally.

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

pub fn main() void {
    const numbers = [_]u8{ 1, 2, 3 };

    for (numbers) |n| {
        std.debug.print("{}\n", .{n});
    } else {
        std.debug.print("done\n", .{});
    }
}
```

This prints:

```text
1
2
3
done
```

If the loop exits with `break`, the `else` branch does not run.

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

pub fn main() void {
    const numbers = [_]u8{ 1, 2, 3 };

    for (numbers) |n| {
        if (n == 2) {
            break;
        }

        std.debug.print("{}\n", .{n});
    } else {
        std.debug.print("done\n", .{});
    }
}
```

This prints:

```text
1
```

The loop stopped early, so `else` did not run.

This is useful for search logic.

#### Searching with `for`

Suppose you want to know whether an array contains a value.

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

pub fn main() void {
    const numbers = [_]u8{ 3, 6, 9, 12 };
    const target: u8 = 9;

    const found = for (numbers) |n| {
        if (n == target) {
            break true;
        }
    } else false;

    std.debug.print("found = {}\n", .{found});
}
```

This prints:

```text
found = true
```

Read it like this:

loop through the numbers

if we find the target, stop and return `true`

if the loop finishes without finding it, return `false`

This is compact, but still explicit.

#### Looping Over Two Collections

A `for` loop can walk through multiple collections at the same time.

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

pub fn main() void {
    const names = [_][]const u8{ "Ada", "Bob", "Cora" };
    const scores = [_]u8{ 90, 75, 88 };

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

This prints:

```text
Ada: 90
Bob: 75
Cora: 88
```

The first capture comes from the first collection.

The second capture comes from the second collection.

```zig
for (names, scores) |name, score| {
```

`name` comes from `names`.

`score` comes from `scores`.

The collections must have compatible lengths for the loop.

#### Ignoring a Value

Sometimes you do not need one of the captured values.

Use `_` to ignore it.

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

for (values, 0..) |_, index| {
    std.debug.print("index = {}\n", .{index});
}
```

This prints:

```text
index = 0
index = 1
index = 2
```

The item itself is ignored. Only the index is used.

#### `for` vs `while`

Use `for` when you are walking through known items.

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

Use `while` when repetition depends on a condition.

```zig
while (remaining > 0) {
    // keep working
}
```

Use `for` for arrays, slices, strings, and ranges.

Use `while` for open-ended loops, retry loops, and loops that stop based on changing state.

#### The Main Idea

A `for` loop walks through items.

It is the normal Zig tool for arrays, slices, strings, and ranges.

The most important forms are:

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

```zig
for (items, 0..) |item, index| {
    // use item and index
}
```

```zig
for (&items) |*item| {
    // modify item
}
```

Keep this rule in mind: use `for` when you already have things to visit. Use `while` when you only have a condition.

