Optionals

?T makes nullability explicit. Plain *T is never null.

var maybe: ?i32 = null;
maybe = 42;

// 1. orelse: provide a default
const a = maybe orelse 0;

// 2. .? : unwrap or panic (asserts non-null)
const b = maybe.?;

// 3. if capture
if (maybe) |value| {
    std.debug.print("{d}\n", .{value});
}

// 4. Pointer capture to modify in place
if (maybe) |*value| value.* += 1;

// 5. orelse with control flow
const c = maybe orelse return;            // or: orelse break, orelse continue, orelse unreachable
_ = .{ a, b, c };

// Optional pointers have the same size as normal pointers (null = address 0)
var node: ?*Node = null;
while (node) |n| : (node = n.next) {
    std.debug.print("{d}\n", .{n.value});
}

fn find(items: []const i32, target: i32) ?usize {
    for (items, 0..) |item, i| if (item == target) return i;
    return null;
}