For Loops

A for loop can iterate over a range of integers:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    for (1..5) |i|
        print("{} ", .{i});
    print("\n", .{});
}
$ zig run for-integers.zig 
1 2 3 4 

We can also use it to go over an array or slice:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    const numbers = [_]f64{ 4, 5, 3, 6 };
    for (numbers) |n|
        print("{} ", .{n});
    print("\n", .{});
}
$ zig run for-slice.zig 
4 5 3 6 

We can add the index to each element:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    const numbers = [_]f64{ 4, 5, 3, 6 };
    for (numbers, 0..) |n, i|
        print("{}:{} ", .{ i, n });
    print("\n", .{});
}
$ zig run with-index.zig 
0:4 1:5 2:3 3:6 

We can also iterate over multiple arrays/slices at the same time as long as they have the same length:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    const numbers = [_]f64{ 4, 5, 3, 6 };
    const even = [_]bool{ true, false, false, true };
    for (numbers, even) |n, e|
        print("{}:{s} ", .{
            n,
            if (e) "even" else "odd",
        });
    print("\n", .{});
}
$ zig run for-multiple.zig 
4:even 5:odd 3:odd 6:even 

If we want to modify the elements, we can iterate by reference to get a pointer to each element:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    var numbers = [_]f64{ 4, 5, 3, 6 };
    for (&numbers) |*n|
        n.* = 10 + n.*;
    for (numbers) |n|
        print("{} ", .{n});
    print("\n", .{});
}
$ zig run for-pointers.zig 
14 15 13 16 

Like a while, we can use a for as an expression if we add an else clause:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    const numbers = [_]f64{ 4, 5, 3, 6 };
    var sum: f64 = 0;
    const count: f64 = numbers.len;
    const average = for (numbers) |n| {
        sum += n;
    } else sum / count;
    print("average: {}\n", .{average});
}
$ zig run for-expression.zig 
average: 4.5

If we have multiple nested loops, we can give a label to a break or continue to specify which loop it should apply to:

const std = @import("std");
const print = std.debug.print;

pub fn main() void {
    const as = [_]f64{ 10, 20, 30 };
    const bs = [_]f64{ 20, 21, 22 };
    outer: for (as) |a| {
        for (bs) |b| {
            if (a == b) {
                print("found {} in both\n", .{a});
                break :outer;
            }
        }
    }
}
$ zig run for-label.zig 
found 20 in both

Next example: Blocks.