# For Loops

> Iterate over sequences and ranges, never a bare counter.

```zig
const std = @import("std");
const expect = std.testing.expect;

test "iterate values" {
    const string = [_]u8{ 'a', 'b', 'c' };
    var count: usize = 0;
    for (string) |character| {
        if (character == 'b') count += 1;
    }
    try expect(count == 1);
}

test "iterate with an index" {
    const string = [_]u8{ 'a', 'b', 'c' };
    var last_index: usize = 0;
    for (string, 0..) |_, index| {
        last_index = index;
    }
    try expect(last_index == 2);
}

test "ranges" {
    var sum: usize = 0;
    for (0..5) |i| sum += i;
    try expect(sum == 10);
}

test "iterate two sequences at once" {
    // Multi-object `for` requires equal lengths; a mismatch is checked.
    const names = [_][]const u8{ "a", "b" };
    const scores = [_]u8{ 1, 2 };
    var total: u8 = 0;
    for (names, scores) |name, score| {
        _ = name;
        total += score;
    }
    try expect(total == 3);
}

test "mutate through a pointer capture" {
    var numbers = [_]u8{ 1, 2, 3 };
    for (&numbers) |*n| n.* *= 2;
    try expect(numbers[2] == 6);
}
```

*Runnable: compiled to WebAssembly and executed by CI against Zig master. (`02-language.for-loops`)*

Zig's `for` iterates over something: a slice, an array, a range. There is no
three-clause `for (i = 0; i < n; i++)`; that is what `while` is for. The result
is that the common case carries no opportunity for an off-by-one.

## Indices are opt-in

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

The `0..` is a second sequence to iterate in lockstep, not special syntax. You
only pay for the index when you ask for it.

## Iterating several sequences together

The same mechanism zips any number of sequences:

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

Lengths must match. A mismatch is checked, so this cannot silently read past
the end of the shorter one.

## Mutating in place

Capturing by value gives you a copy. To modify the underlying elements, iterate
over a pointer to the array and capture by pointer:

```zig
for (&numbers) |*n| n.* *= 2;
```
