Hello everyone. I was doing my daily dose of Ziglings to help me get more confident with the language, and I found myself with a syntactical problem.
I know that you can use IF blocks as expressions to populate variables like:
const x = if (getNumber()) |n| n else |err| switch (err) { NumError.IllegalNumber => 42, };
Where var is a Union Error type.
I was trying to achieve the same elegant result with a multiline if but I found myself incapable to make the if behave as an expression. I tried for example:
const x = if (getNumber()) |n| {
dothings(n);
return n;
} else |err| switch (err) { NumError.IllegalNumber => 42, };
And other variations of return n
like just n
without ;
.
Is it possible right now to achieve what I’m trying to obtain with this specific syntax?
PS: My Zig version right now is 0.11.0-dev.4334+928d43f61
You can break from a labelled block like this:
const x = if (getNumber()) |n| block: {
dothings(n);
break :block n;
} else |err| switch (err) { NumError.IllegalNumber => 42, };
1 Like
Return is for functions. For blocks, you want to name the block and use break. Break can “return” stuff as well. Works for any any block, like if, while, for and even unnamed blocks.
const x = if (getNumber()) |n| blk: {
dothings(n);
break :blk n;
} else |err| switch (err) { NumError.IllegalNumber => 42, };
Rleevant part of the documentation: Documentation - The Zig Programming Language
1 Like
Thank you very much!
It seems uselessly verbose as a syntax, are there plans to improve it in the future that you know?
are there plans to improve it in the future that you know?
Not as far I know.
Note however that in some cases there might be a better way to do this:
- If you always want to output 42 regardless of the error, then you can omit the switch case:
const x = if (getNumber()) |n| block: {
dothings(n);
break :block n;
} else 42;
- Maybe it makes sense to put the
dothings(n)
functions into the logic of getNumber()
or maybe create a new function getNumberAndDoThings()
:
fn getNumberAndDoThings() !i32 {
return dothings(try getNumber());
}
const x = if (getNumberAndDoThings()) |n| n else 42;
And for this you can also use catch
:
const x = getNumberAndDoThings() catch 42;
2 Likes
Welcome to the forum @eisterman, I’m going to mark the answer by @IntegratedQuantum as the solution to this thread.
1 Like
Would perhaps be great if, every time you do const foo = ...
, the :foo
label was automatically in scope. I’ve noticed that most of the time you use break
sytnax it is for
const thing = thing: {
...
break :thing value
};
pattern.
Or maybe not — Zig is relatively sugar-free, there are benefits to keep it that way.
2 Likes