summaryrefslogtreecommitdiff
path: root/exercises
diff options
context:
space:
mode:
authorNuno Mendes <98030270+nm-remarkable@users.noreply.github.com>2024-09-18 23:26:33 +0200
committerNuno Mendes <98030270+nm-remarkable@users.noreply.github.com>2024-09-18 23:26:33 +0200
commited1a20d51b4d319a32adb7d1552f7316599c3d60 (patch)
treee83036d0ac97fa3f7af1f8020772593a5cb5da76 /exercises
parentd9ce18631d160a011a64bbdea19b64a2fd65a523 (diff)
improve explanantions in labeled switch
Diffstat (limited to 'exercises')
-rw-r--r--exercises/108_labeled_switch.zig59
1 files changed, 49 insertions, 10 deletions
diff --git a/exercises/108_labeled_switch.zig b/exercises/108_labeled_switch.zig
index dfc061a..0748d9d 100644
--- a/exercises/108_labeled_switch.zig
+++ b/exercises/108_labeled_switch.zig
@@ -1,15 +1,54 @@
//
-// A labeled switch in zig allows the usage of continue and break
-// just like loops, these allow you to create very concise
-// Finite State Automata to represent state transitions
+// 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.
//
-// foo: switch (state) {
-// 1 => continue :foo 2,
-// 2 => continue :foo 3,
-// 3 => break :foo,
-// 4 => {},
-// ...
-// }
+// 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");