Skip to content

`while` Loops

A while loop repeats while a condition is true.

while Loops

A while loop repeats while a condition is true.

var i: usize = 0;

while (i < 5) {
    std.debug.print("{d}\n", .{i});
    i += 1;
}

The output is:

0
1
2
3
4

The condition must be a boolean. Zig does not treat integers as true or false.

This is correct:

while (i != 0) {
    i -= 1;
}

This is wrong:

while (i) {
    i -= 1;
}

The compiler rejects it because i is an integer, not a boolean.

A while loop may have a continue expression. It runs after each iteration, just before the next condition check.

var i: usize = 0;

while (i < 5) : (i += 1) {
    std.debug.print("{d}\n", .{i});
}

This prints the same numbers as before.

The continue expression is useful when the loop has one regular step.

var n: usize = 10;

while (n > 0) : (n -= 1) {
    std.debug.print("{d}\n", .{n});
}

The condition is checked before the body runs. If it is false at the start, the body does not run.

var i: usize = 10;

while (i < 5) {
    std.debug.print("never printed\n", .{});
}

A while loop can be infinite.

while (true) {
    // repeat forever
}

Use break to leave a loop.

var i: usize = 0;

while (true) {
    if (i == 5) break;
    std.debug.print("{d}\n", .{i});
    i += 1;
}

Use continue to skip to the next iteration.

var i: usize = 0;

while (i < 10) : (i += 1) {
    if (i % 2 == 0) continue;
    std.debug.print("{d}\n", .{i});
}

This prints only odd numbers.

while can also be an expression. A loop expression may have an else branch. The else branch runs when the loop ends normally, not when it ends by break.

var i: usize = 0;

while (i < 3) : (i += 1) {
    std.debug.print("{d}\n", .{i});
} else {
    std.debug.print("done\n", .{});
}

The output is:

0
1
2
done

If the loop breaks, the else branch does not run.

var i: usize = 0;

while (i < 3) : (i += 1) {
    if (i == 1) break;
    std.debug.print("{d}\n", .{i});
} else {
    std.debug.print("done\n", .{});
}

The output is:

0

The word done is not printed.

A while loop can produce a value by breaking with a value.

var i: usize = 0;

const answer = while (i < 10) : (i += 1) {
    if (i == 7) break i;
} else 0;

Here answer is 7.

The else value is used if the loop finishes without break.

This is useful for searches.

const data = [_]u8{ 3, 8, 13, 21, 34 };

var i: usize = 0;
const found = while (i < data.len) : (i += 1) {
    if (data[i] == 21) break i;
} else null;

The value of found is the index of the first match, or null if no match is found. Its type is ?usize.

while also has special support for optionals.

var maybe: ?usize = 3;

while (maybe) |value| {
    std.debug.print("{d}\n", .{value});

    if (value == 0) {
        maybe = null;
    } else {
        maybe = value - 1;
    }
}

The loop continues while maybe contains a value. Inside the body, the value is captured as value.

This prints:

3
2
1
0

After maybe becomes null, the loop stops.

This form is common when repeatedly asking for the next item from an operation that may stop.

while (next()) |item| {
    use(item);
}

A loop should keep its moving parts visible. Put the condition near the top. Put the regular update in the continue expression when there is one. Use break for the exceptional exit, not for the ordinary shape of the loop.

Exercise 3-13. Write a while loop that prints the numbers from 1 to 10.

Exercise 3-14. Write a loop that prints only even numbers below 20.

Exercise 3-15. Write a search loop that finds the first zero in an array.

Exercise 3-16. Change the search loop so it returns null when no zero is present.