Merge pull request 'Add a new exercise for a labeled switch' (#161) from nm-remarkable/exercises:main into main

Reviewed-on: https://codeberg.org/ziglings/exercises/pulls/161
This commit is contained in:
Chris Boesch 2024-09-19 10:16:08 +00:00
commit 94b5b4bf4b
4 changed files with 105 additions and 3 deletions

View file

@ -88,7 +88,8 @@ that if you update one, you may need to also update the other.
### Version Changes ### Version Changes
Version-0.14.0-dev.1224 Version-0.14.0-dev.1573
* *2024-09-16* zig 0.14.0-dev.1573 - introduction of labeled switch, see [#21257](https://github.com/ziglang/zig/pull/21257)
* *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225) * *2024-09-02* zig 0.14.0-dev.1409 - several changes in std.builtin, see [#21225](https://github.com/ziglang/zig/pull/21225)
* *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115) * *2024-08-04* zig 0.14.0-dev.1224 - several changes in build system, see [#21115](https://github.com/ziglang/zig/pull/21115)
* *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600) * *2024-08-04* zig 0.14.0-dev.839 - several changes in build system, see [#20580](https://github.com/ziglang/zig/pull/20580), [#20600](https://github.com/ziglang/zig/issues/20600)
@ -229,7 +230,7 @@ Zig Core Language
* [X] Bit manipulation * [X] Bit manipulation
* [X] Working with C * [X] Working with C
* [X] Threading * [X] Threading
* [ ] Labeled switch (#21257) * [x] Labeled switch
Zig Standard Library Zig Standard Library

View file

@ -15,7 +15,7 @@ const print = std.debug.print;
// 1) Getting Started // 1) Getting Started
// 2) Version Changes // 2) Version Changes
comptime { comptime {
const required_zig = "0.14.0-dev.1409"; const required_zig = "0.14.0-dev.1573";
const current_zig = builtin.zig_version; const current_zig = builtin.zig_version;
const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable;
if (current_zig.order(min_zig) == .lt) { if (current_zig.order(min_zig) == .lt) {
@ -1197,6 +1197,12 @@ const exercises = [_]Exercise{
\\Successfully Read 18 bytes: It's zigling time! \\Successfully Read 18 bytes: It's zigling time!
, ,
}, },
.{
.main_file = "108_labeled_switch.zig",
.output =
\\The pull request has been merged
,
},
.{ .{
.main_file = "999_the_end.zig", .main_file = "999_the_end.zig",
.output = .output =

View file

@ -0,0 +1,77 @@
//
// You've heard of while loops in exercises 011,012,013 and 014
// You've also heard of switch expressions in exercises 030 and 31.
// You've also seen how labels can be used in exercise 063.
//
// By combining while loops and switch statements with continue and break statements
// one can create very concise State Machines.
//
// One such example would be:
//
// pub fn main() void {
// var op: u8 = 1;
// while (true) {
// switch (op) {
// 1 => { op = 2; continue; },
// 2 => { op = 3; continue; },
// 3 => return,
// 4 => {},
// }
// break;
// }
// std.debug.print("This statement cannot be reached");
// }
//
// By combining all we've learned so far, we can now proceed with a labeled switch
//
// A labeled switch is some extra syntatic sugar, which comes with all sorts of
// candy (performance benefits). Don't believe me? Directly to source https://github.com/ziglang/zig/pull/21367
//
// Here is the previous excerpt implemented as a labeled switch instead:
//
// pub fn main() void {
// foo: switch (@as(u8, 1)) {
// 1 => continue :foo 2,
// 2 => continue :foo 3,
// 3 => return,
// 4 => {},
// }
// std.debug.print("This statement cannot be reached");
// }
//
// The flow of execution on this second case is:
// 1. The switch starts with value '1';
// 2. The switch evaluates to case '1' which in turn uses the continue statement
// to re-evaluate the labeled switch again, now providing the value '2';
// 3. In the case '2' we repeat the same pattern as case '1'
// but instead the value to be evaluated is now '3';
// 4. Finally we get to case '3', where we return from the function as a whole.
//
// Since step 4 or a break stament do not exist in this switch, the debug statement is
// never executed
//
const std = @import("std");
const PullRequestState = enum(u8) {
Draft,
InReview,
Approved,
Rejected,
Merged,
};
pub fn main() void {
// Oh no, your pull request keeps being rejected,
// how would you fix it?
pr: switch (@as(PullRequestState, PullRequestState.Draft)) {
PullRequestState.Draft => continue :pr PullRequestState.InReview,
PullRequestState.InReview => continue :pr PullRequestState.Rejected,
PullRequestState.Approved => continue :pr PullRequestState.Merged,
PullRequestState.Rejected => {
std.debug.print("The pull request has been rejected", .{});
return;
},
PullRequestState.Merged => break, // Would you know where to break to?
}
std.debug.print("The pull request has been merged", .{});
}

View file

@ -0,0 +1,18 @@
--- a/exercises/108_labeled_switch.zig
+++ b/exercises/108_labeled_switch.zig
@@ -65,13 +65,13 @@ pub fn main() void {
// how would you fix it?
pr: switch (@as(PullRequestState, PullRequestState.Draft)) {
PullRequestState.Draft => continue :pr PullRequestState.InReview,
- PullRequestState.InReview => continue :pr PullRequestState.Rejected,
+ PullRequestState.InReview => continue :pr PullRequestState.Approved,
PullRequestState.Approved => continue :pr PullRequestState.Merged,
PullRequestState.Rejected => {
std.debug.print("The pull request has been rejected", .{});
return;
},
- PullRequestState.Merged => break, // Would you know where to break to?
+ PullRequestState.Merged => break :pr, // Would you know where to break to?
}
std.debug.print("The pull request has been merged", .{});
}