An Introduction To Zig

I taught someone how to use Zig for the first time. This is what they wrote.

const std = @import("std");

pub fn main() !void {
    const types = .{ [2]u32, [3]u12, [4]u8 };
    var x: usize = 1;
    inline for (types) |T| {
        var numbers = @as(T, undefined);
        for (0.., std.os.argv[x .. x + @typeInfo(T).Array.len]) |i, arg| {
            numbers[i] = try std.fmt.parseInt(@typeInfo(T).Array.child, std.mem.span(arg), 10);
        }
        x += @typeInfo(T).Array.len;
        const text = "Hello, World!\n";
        // @compileError(std.fmt.comptimePrint("{} lines", .{group(true, &numbers, text, .{})}));
        std.debug.print("{}", .{group(false, &numbers, text, .{})});
    }
}

fn group(comptime is_comptime: bool, s: anytype, comptime t: []const u8, arg: anytype) if (is_comptime) comptime_int else usize {
    inline for (t) |c| {
        if (c == 'a') {
            @compileError("NO As :(((((");
        }
    }
    if (s.len == 0) {
        if (!is_comptime)
            std.debug.print(t, arg);
        return 1;
    } else {
        var x: if (is_comptime) comptime_int else usize = 0;
        for (0..s[0]) |_| {
            x += group(is_comptime, s[1..], t, arg);
            if (!is_comptime)
                std.debug.print("\n", .{});
        }
        return x;
    }
}

test "simple test" {
    var list = std.ArrayList(i32).init(std.testing.allocator);
    defer list.deinit(); // try commenting this out and see if zig detects the memory leak!
    try list.append(42);
    try std.testing.expectEqual(@as(i32, 42), list.pop());
}

I should probably clean this up and make this a proper tutorial. For now, try to understand how this program works by compiling it with Zig 0.12.0 (download it here) and running it. Every token has a purpose.