// // 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, // else => {}, // } // 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. // 5. In this example as the input has no clear exhaustive patterns but a essentially // any u8 integer, we need do need to handle any case that is not explicitly handled // by using the `else => {}` branch as a default case. // // 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 (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.\n", .{}); return; }, PullRequestState.Merged => break, // Would you know where to break to? } std.debug.print("The pull request has been merged.\n", .{}); }