Zig Notes

zig gems
Login

zig gems

the standard library

  1. std.math is surprisingly rich
  2. std.fs is surprisingly robust, using file operations with reference to a directory as the 'default'.

defer

Zig Defer Patterns

  1. as an alternative to RAII
  2. simple contract programming
  3. statically enforcing the absence of errors: errdefer comptime unreachable
  4. logging errors: errdefer

inline

inline in Zig is not a semantically neutral hint: it always takes effect, and it has semantic meaning.

  1. it seems like inline functions can allocate on the caller's stack:
    const std = @import("std");
    
    const Point = struct { x: i32, y: i32 };
    
    /// returned pointer is to an object on the caller's stack.
    inline fn f(n: i32) *const Point {
        return &.{ .x = n, .y = n };
    }
    
    /// returned pointer is to an object on g()'s stack during the call to g(),
    /// which becomes invalid after it returns.
    fn g(n: i32) *const Point {
        return &.{ .x = n, .y = n };
    }
    
    test f {
        const p1 = f(2);
        const p2: Point = .{ .x = 0, .y = 0 };
        const p3 = f(4);
        var p4: Point = undefined;
        p4.x = p1.x;
        p4.y = p2.y + p3.y;
        std.debug.print("{}\n", .{p1});
        std.debug.print("{}\n", .{p2});
        std.debug.print("{}\n", .{p3});
        std.debug.print("{}\n", .{p4});
    }
    
    test g {
        const p1 = g(2);
        const p2: Point = .{ .x = 0, .y = 0 };
        const p3 = g(4);
        var p4: Point = undefined;
        p4.x = p1.x;
        p4.y = p2.y + p3.y;
        std.debug.print("{}\n", .{p1});
        std.debug.print("{}\n", .{p2});
        std.debug.print("{}\n", .{p3});
        std.debug.print("{}\n", .{p4});
    }
  2. inline loops can expand over disparate types:
    test "what type is x?" {
        inline for (&.{ 1, true, "a string", .{ 0, 5 } }) |x| {
            @compileLog(@TypeOf(x));
        }
    }
    Compile Log Output:
    @as(type, comptime_int)
    @as(type, bool)
    @as(type, *const [8:0]u8)
    @as(type, struct{comptime comptime_int = 0, comptime comptime_int = 5})
  3. something I don't quite get: you can inline a stub to prevent more involved codegen: discord reference.
  4. inline functions can detect if a parameter is comptime-known:
    const std = @import("std");
    
    inline fn comptime_known(x: anytype) bool {
        // 0.14.0-dev.2034
        return @typeInfo(@TypeOf(.{x})).@"struct".fields[0].is_comptime;
    }
    
    test {
        try std.testing.expectEqual(true, comptime_known(1));
        const x: i32 = 1;
        try std.testing.expectEqual(true, comptime_known(x));
        try std.testing.expectEqual(false, comptime_known(std.time.timestamp()));
    }