How to assign the result of an if block to a variable?

I’m trying to assign the result of an if block to a variable out_path in Zig, but the way I’m doing it doesn’t seem to work. Here’s my code:

const out_path: ?[]const u8 = if (out_target != Target.None) {
    const path: []const u8 = switch (out_target) {
        Target.Stdout => out_target.Stdout,
        Target.Stderr => out_target.Stderr,
        Target.Both => out_target.Both,
        else => unreachable,
    };
    if (path.len != 0) {
        path;
    }
    null;
};

In this code, I want out_path to be assigned the value of path if path.len != 0, otherwise it should be null. However, the current approach doesn’t work.
Also in general can I do something like this:

const out = {
...
...
return 5; // assign to `out`
};

Compared to Rust, where blocks implicitly return the last value, in Zig, you need to use break with a label to return a value from a block. Relevant language reference section.

const out_path: ?[]const u8 = if (out_target != Target.None) out_path: {
    const path: []const u8 = switch (out_target) {
        Target.Stdout => out_target.Stdout,
        Target.Stderr => out_target.Stderr,
        Target.Both => out_target.Both,
        else => unreachable,
    };
    if (path.len != 0) {
        break :out_path path;
    }
    break :out_path null;
    // or
    // break :out_path if (path.len != 0) path else null;
};
6 Likes

You can do it if you omit to put brackets for the scope like so if you have a small logic

pub fn foo(bar: usize, maybe_bat: ?usize) void {
    const baz = if (bar == 7) bar else 0;
    const bag = if (maybe_bat) |bat| bat else 0;
}

or like this but it’s kind of ugly if you ask me.

pub fn foo(bar: usize, maybe_bat: ?usize) void {
    const baz =
        if (bar == 7)
            bar
        else
            0;
    const bag = if (maybe_bat) |bat|
        bat
    else
        0;
}
2 Likes

Thanks @AndrewKraevskii

1 Like