Day 6: Ziglings exercises 030 - 034
On the 6th day of our 1000-day journey with Zig, most of the time was spent working on Ziglings. Presently we are at almost the 30th exercise mark, with a few more dozen to go. So far enjoying the learning and totally loving it.
Switch
Yesterday we looked at defer, errdefer among other things, today we get back to control flow selection using switch statements. Zig’s switch works as both a statement and an expression. The types of all branches must coerce to the type which is being switched upon. All possible values must have an associated branch - values cannot be left out. Cases cannot fall through to other branches.With switch statements one can match possible values of an expression, thereby performing different actions based on each value.
switch (players) {
1 => startOnePlayerGame(),
2 => startTwoPlayerGame(),
else => {
alert();
return GameError.TooManyPlayers;
}
}
This is similar to having this:
if (players == 1) startOnePlayerGame();
else if (players == 2) startTwoPlayerGame();
else {
alert();
return GameError.TooManyPlayers;
}
Switch as expressions
Like if statements, one can use switch statements as expressions which return values that you can later use in your program.
const a = switch (x) {
1 => 9,
2 => 16,
3 => 7,
...
}
Unreachable Statement
Something unique to Zig is the unreachable statement, which is used when you want to tell the compiler that a given part of the code should not be executed, where reaching that part of the code is deemed an error. unreachable is an assertion to the compiler that this statement will not be reached.
if (true) {
...
} else {
unreachable;
}
It can tell the compiler that a branch is impossible, which the optimiser can then take advantage of. Reaching an unreachable is detectable illegal behaviour. As it is of the type noreturn, it is compatible with all other types. Here it coerces to u32.
test "unreachable" {
const x: i32 = 1;
const y: u32 = if (x == 2) 5 else unreachable;
_ = y;
}
Unreachable with a switch:
const expect = @import("std").testing.expect;
fn asciiToUpper(x: u8) u8 {
return switch (x) {
'a'...'z' => x + 'A' - 'a',
'A'...'Z' => x,
else => unreachable,
};
}
test "unreachable switch" {
try expect(asciiToUpper('a') == 'A');
try expect(asciiToUpper('A') == 'A');
}
If error
We have looked at a number of ways of handling errors such as using catch and try; another variation is using the if statement.
if (foo) |value| {
// foo was NOT an error; value is the non-error value of foo
} else |err| {
// foo WAS an error; err is the error value of foo
}
You can resort to using a switch statement in this scenario, as shown below:
if (foo) |value| {
...
} else |err| switch (err) {
...
}
This is similar but a different variation of the above statement.
What I Learned Today
- Switch statement in Zig
- Unreachable statements in Zig.
- using if error statements.
Looking Ahead
Tomorrow, is Saturday, I may take a short break but will find a way to doing something in Zig, you will see what I will write about in my 7 days of Zig.
References
Comments