summaryrefslogtreecommitdiffstatshomepage
path: root/exercises
diff options
context:
space:
mode:
Diffstat (limited to 'exercises')
-rw-r--r--exercises/001_hello.zig (renamed from exercises/01_hello.zig)0
-rw-r--r--exercises/002_std.zig (renamed from exercises/02_std.zig)0
-rw-r--r--exercises/003_assignment.zig (renamed from exercises/03_assignment.zig)0
-rw-r--r--exercises/004_arrays.zig (renamed from exercises/04_arrays.zig)0
-rw-r--r--exercises/005_arrays2.zig (renamed from exercises/05_arrays2.zig)0
-rw-r--r--exercises/006_strings.zig (renamed from exercises/06_strings.zig)0
-rw-r--r--exercises/007_strings2.zig (renamed from exercises/07_strings2.zig)0
-rw-r--r--exercises/008_quiz.zig (renamed from exercises/08_quiz.zig)0
-rw-r--r--exercises/009_if.zig (renamed from exercises/09_if.zig)0
-rw-r--r--exercises/010_if2.zig (renamed from exercises/10_if2.zig)0
-rw-r--r--exercises/011_while.zig (renamed from exercises/11_while.zig)0
-rw-r--r--exercises/012_while2.zig (renamed from exercises/12_while2.zig)0
-rw-r--r--exercises/013_while3.zig (renamed from exercises/13_while3.zig)0
-rw-r--r--exercises/014_while4.zig (renamed from exercises/14_while4.zig)0
-rw-r--r--exercises/015_for.zig (renamed from exercises/15_for.zig)0
-rw-r--r--exercises/016_for2.zig (renamed from exercises/16_for2.zig)0
-rw-r--r--exercises/017_quiz2.zig (renamed from exercises/17_quiz2.zig)0
-rw-r--r--exercises/018_functions.zig (renamed from exercises/18_functions.zig)0
-rw-r--r--exercises/019_functions2.zig (renamed from exercises/19_functions2.zig)0
-rw-r--r--exercises/020_quiz3.zig (renamed from exercises/20_quiz3.zig)0
-rw-r--r--exercises/021_errors.zig (renamed from exercises/21_errors.zig)0
-rw-r--r--exercises/022_errors2.zig (renamed from exercises/22_errors2.zig)6
-rw-r--r--exercises/023_errors3.zig (renamed from exercises/23_errors3.zig)0
-rw-r--r--exercises/024_errors4.zig (renamed from exercises/24_errors4.zig)0
-rw-r--r--exercises/025_errors5.zig (renamed from exercises/25_errors5.zig)0
-rw-r--r--exercises/026_hello2.zig (renamed from exercises/26_hello2.zig)0
-rw-r--r--exercises/027_defer.zig (renamed from exercises/27_defer.zig)0
-rw-r--r--exercises/028_defer2.zig (renamed from exercises/28_defer2.zig)0
-rw-r--r--exercises/029_errdefer.zig (renamed from exercises/29_errdefer.zig)0
-rw-r--r--exercises/030_switch.zig (renamed from exercises/30_switch.zig)0
-rw-r--r--exercises/031_switch2.zig (renamed from exercises/31_switch2.zig)0
-rw-r--r--exercises/032_unreachable.zig (renamed from exercises/32_unreachable.zig)0
-rw-r--r--exercises/033_iferror.zig (renamed from exercises/33_iferror.zig)0
-rw-r--r--exercises/034_quiz4.zig (renamed from exercises/34_quiz4.zig)0
-rw-r--r--exercises/035_enums.zig (renamed from exercises/35_enums.zig)0
-rw-r--r--exercises/036_enums2.zig (renamed from exercises/36_enums2.zig)0
-rw-r--r--exercises/037_structs.zig (renamed from exercises/37_structs.zig)0
-rw-r--r--exercises/038_structs2.zig (renamed from exercises/38_structs2.zig)0
-rw-r--r--exercises/039_pointers.zig (renamed from exercises/39_pointers.zig)0
-rw-r--r--exercises/040_pointers2.zig (renamed from exercises/40_pointers2.zig)0
-rw-r--r--exercises/041_pointers3.zig (renamed from exercises/41_pointers3.zig)0
-rw-r--r--exercises/042_pointers4.zig (renamed from exercises/42_pointers4.zig)0
-rw-r--r--exercises/043_pointers5.zig (renamed from exercises/43_pointers5.zig)0
-rw-r--r--exercises/044_quiz5.zig (renamed from exercises/44_quiz5.zig)0
-rw-r--r--exercises/045_optionals.zig (renamed from exercises/45_optionals.zig)0
-rw-r--r--exercises/046_optionals2.zig (renamed from exercises/46_optionals2.zig)0
-rw-r--r--exercises/047_methods.zig (renamed from exercises/47_methods.zig)0
-rw-r--r--exercises/048_methods2.zig (renamed from exercises/48_methods2.zig)4
-rw-r--r--exercises/049_quiz6.zig (renamed from exercises/49_quiz6.zig)0
-rw-r--r--exercises/050_no_value.zig (renamed from exercises/50_no_value.zig)0
-rw-r--r--exercises/051_values.zig (renamed from exercises/51_values.zig)0
-rw-r--r--exercises/052_slices.zig49
-rw-r--r--exercises/053_slices2.zig35
-rw-r--r--exercises/054_manypointers.zig55
-rw-r--r--exercises/055_unions.zig76
-rw-r--r--exercises/056_unions2.zig64
-rw-r--r--exercises/057_unions3.zig54
57 files changed, 340 insertions, 3 deletions
diff --git a/exercises/01_hello.zig b/exercises/001_hello.zig
index d2093c7..d2093c7 100644
--- a/exercises/01_hello.zig
+++ b/exercises/001_hello.zig
diff --git a/exercises/02_std.zig b/exercises/002_std.zig
index 50059e1..50059e1 100644
--- a/exercises/02_std.zig
+++ b/exercises/002_std.zig
diff --git a/exercises/03_assignment.zig b/exercises/003_assignment.zig
index 6a4364b..6a4364b 100644
--- a/exercises/03_assignment.zig
+++ b/exercises/003_assignment.zig
diff --git a/exercises/04_arrays.zig b/exercises/004_arrays.zig
index 88fcc78..88fcc78 100644
--- a/exercises/04_arrays.zig
+++ b/exercises/004_arrays.zig
diff --git a/exercises/05_arrays2.zig b/exercises/005_arrays2.zig
index 9282a31..9282a31 100644
--- a/exercises/05_arrays2.zig
+++ b/exercises/005_arrays2.zig
diff --git a/exercises/06_strings.zig b/exercises/006_strings.zig
index 6258816..6258816 100644
--- a/exercises/06_strings.zig
+++ b/exercises/006_strings.zig
diff --git a/exercises/07_strings2.zig b/exercises/007_strings2.zig
index 6350be1..6350be1 100644
--- a/exercises/07_strings2.zig
+++ b/exercises/007_strings2.zig
diff --git a/exercises/08_quiz.zig b/exercises/008_quiz.zig
index eda66b8..eda66b8 100644
--- a/exercises/08_quiz.zig
+++ b/exercises/008_quiz.zig
diff --git a/exercises/09_if.zig b/exercises/009_if.zig
index 284563d..284563d 100644
--- a/exercises/09_if.zig
+++ b/exercises/009_if.zig
diff --git a/exercises/10_if2.zig b/exercises/010_if2.zig
index d0c8cac..d0c8cac 100644
--- a/exercises/10_if2.zig
+++ b/exercises/010_if2.zig
diff --git a/exercises/11_while.zig b/exercises/011_while.zig
index 674d904..674d904 100644
--- a/exercises/11_while.zig
+++ b/exercises/011_while.zig
diff --git a/exercises/12_while2.zig b/exercises/012_while2.zig
index ef53ea0..ef53ea0 100644
--- a/exercises/12_while2.zig
+++ b/exercises/012_while2.zig
diff --git a/exercises/13_while3.zig b/exercises/013_while3.zig
index 4cccf62..4cccf62 100644
--- a/exercises/13_while3.zig
+++ b/exercises/013_while3.zig
diff --git a/exercises/14_while4.zig b/exercises/014_while4.zig
index 7b2714e..7b2714e 100644
--- a/exercises/14_while4.zig
+++ b/exercises/014_while4.zig
diff --git a/exercises/15_for.zig b/exercises/015_for.zig
index 2ce930e..2ce930e 100644
--- a/exercises/15_for.zig
+++ b/exercises/015_for.zig
diff --git a/exercises/16_for2.zig b/exercises/016_for2.zig
index 0a62a1a..0a62a1a 100644
--- a/exercises/16_for2.zig
+++ b/exercises/016_for2.zig
diff --git a/exercises/17_quiz2.zig b/exercises/017_quiz2.zig
index 7de7010..7de7010 100644
--- a/exercises/17_quiz2.zig
+++ b/exercises/017_quiz2.zig
diff --git a/exercises/18_functions.zig b/exercises/018_functions.zig
index 51be2cd..51be2cd 100644
--- a/exercises/18_functions.zig
+++ b/exercises/018_functions.zig
diff --git a/exercises/19_functions2.zig b/exercises/019_functions2.zig
index 00f33c5..00f33c5 100644
--- a/exercises/19_functions2.zig
+++ b/exercises/019_functions2.zig
diff --git a/exercises/20_quiz3.zig b/exercises/020_quiz3.zig
index 651af8c..651af8c 100644
--- a/exercises/20_quiz3.zig
+++ b/exercises/020_quiz3.zig
diff --git a/exercises/21_errors.zig b/exercises/021_errors.zig
index cbb5ac8..cbb5ac8 100644
--- a/exercises/21_errors.zig
+++ b/exercises/021_errors.zig
diff --git a/exercises/22_errors2.zig b/exercises/022_errors2.zig
index fa0eafa..7bf00d4 100644
--- a/exercises/22_errors2.zig
+++ b/exercises/022_errors2.zig
@@ -2,15 +2,15 @@
// A common case for errors is a situation where we're expecting to
// have a value OR something has gone wrong. Take this example:
//
-// var text: Text = getText('foo.txt');
+// var text: Text = getText("foo.txt");
//
-// What happens if getText() can't find 'foo.txt'? How do we express
+// What happens if getText() can't find "foo.txt"? How do we express
// this in Zig?
//
// Zig lets us make what's called an "error union" which is a value
// which could either be a regular value OR an error from a set:
//
-// var text: MyErrorSet!Text = getText('foo.txt');
+// var text: MyErrorSet!Text = getText("foo.txt");
//
// For now, let's just see if we can try making an error union!
//
diff --git a/exercises/23_errors3.zig b/exercises/023_errors3.zig
index a465737..a465737 100644
--- a/exercises/23_errors3.zig
+++ b/exercises/023_errors3.zig
diff --git a/exercises/24_errors4.zig b/exercises/024_errors4.zig
index 560b129..560b129 100644
--- a/exercises/24_errors4.zig
+++ b/exercises/024_errors4.zig
diff --git a/exercises/25_errors5.zig b/exercises/025_errors5.zig
index 5119dcf..5119dcf 100644
--- a/exercises/25_errors5.zig
+++ b/exercises/025_errors5.zig
diff --git a/exercises/26_hello2.zig b/exercises/026_hello2.zig
index 237d27c..237d27c 100644
--- a/exercises/26_hello2.zig
+++ b/exercises/026_hello2.zig
diff --git a/exercises/27_defer.zig b/exercises/027_defer.zig
index b41e2af..b41e2af 100644
--- a/exercises/27_defer.zig
+++ b/exercises/027_defer.zig
diff --git a/exercises/28_defer2.zig b/exercises/028_defer2.zig
index 6943012..6943012 100644
--- a/exercises/28_defer2.zig
+++ b/exercises/028_defer2.zig
diff --git a/exercises/29_errdefer.zig b/exercises/029_errdefer.zig
index f43c738..f43c738 100644
--- a/exercises/29_errdefer.zig
+++ b/exercises/029_errdefer.zig
diff --git a/exercises/30_switch.zig b/exercises/030_switch.zig
index cb983f5..cb983f5 100644
--- a/exercises/30_switch.zig
+++ b/exercises/030_switch.zig
diff --git a/exercises/31_switch2.zig b/exercises/031_switch2.zig
index b7680b4..b7680b4 100644
--- a/exercises/31_switch2.zig
+++ b/exercises/031_switch2.zig
diff --git a/exercises/32_unreachable.zig b/exercises/032_unreachable.zig
index ffc35a4..ffc35a4 100644
--- a/exercises/32_unreachable.zig
+++ b/exercises/032_unreachable.zig
diff --git a/exercises/33_iferror.zig b/exercises/033_iferror.zig
index 67777a9..67777a9 100644
--- a/exercises/33_iferror.zig
+++ b/exercises/033_iferror.zig
diff --git a/exercises/34_quiz4.zig b/exercises/034_quiz4.zig
index 6b0e3fc..6b0e3fc 100644
--- a/exercises/34_quiz4.zig
+++ b/exercises/034_quiz4.zig
diff --git a/exercises/35_enums.zig b/exercises/035_enums.zig
index 1825f52..1825f52 100644
--- a/exercises/35_enums.zig
+++ b/exercises/035_enums.zig
diff --git a/exercises/36_enums2.zig b/exercises/036_enums2.zig
index 0ddc4a5..0ddc4a5 100644
--- a/exercises/36_enums2.zig
+++ b/exercises/036_enums2.zig
diff --git a/exercises/37_structs.zig b/exercises/037_structs.zig
index 8082248..8082248 100644
--- a/exercises/37_structs.zig
+++ b/exercises/037_structs.zig
diff --git a/exercises/38_structs2.zig b/exercises/038_structs2.zig
index b0db022..b0db022 100644
--- a/exercises/38_structs2.zig
+++ b/exercises/038_structs2.zig
diff --git a/exercises/39_pointers.zig b/exercises/039_pointers.zig
index d545525..d545525 100644
--- a/exercises/39_pointers.zig
+++ b/exercises/039_pointers.zig
diff --git a/exercises/40_pointers2.zig b/exercises/040_pointers2.zig
index 43dd2c3..43dd2c3 100644
--- a/exercises/40_pointers2.zig
+++ b/exercises/040_pointers2.zig
diff --git a/exercises/41_pointers3.zig b/exercises/041_pointers3.zig
index 9e2bcc6..9e2bcc6 100644
--- a/exercises/41_pointers3.zig
+++ b/exercises/041_pointers3.zig
diff --git a/exercises/42_pointers4.zig b/exercises/042_pointers4.zig
index 261dbc1..261dbc1 100644
--- a/exercises/42_pointers4.zig
+++ b/exercises/042_pointers4.zig
diff --git a/exercises/43_pointers5.zig b/exercises/043_pointers5.zig
index cb94189..cb94189 100644
--- a/exercises/43_pointers5.zig
+++ b/exercises/043_pointers5.zig
diff --git a/exercises/44_quiz5.zig b/exercises/044_quiz5.zig
index 8a0d88c..8a0d88c 100644
--- a/exercises/44_quiz5.zig
+++ b/exercises/044_quiz5.zig
diff --git a/exercises/45_optionals.zig b/exercises/045_optionals.zig
index 1327e4c..1327e4c 100644
--- a/exercises/45_optionals.zig
+++ b/exercises/045_optionals.zig
diff --git a/exercises/46_optionals2.zig b/exercises/046_optionals2.zig
index d3f65bb..d3f65bb 100644
--- a/exercises/46_optionals2.zig
+++ b/exercises/046_optionals2.zig
diff --git a/exercises/47_methods.zig b/exercises/047_methods.zig
index c8e5c17..c8e5c17 100644
--- a/exercises/47_methods.zig
+++ b/exercises/047_methods.zig
diff --git a/exercises/48_methods2.zig b/exercises/048_methods2.zig
index f97710d..d15a420 100644
--- a/exercises/48_methods2.zig
+++ b/exercises/048_methods2.zig
@@ -69,3 +69,7 @@ fn visitElephants(first_elephant: *Elephant) void {
//
// 1) drforester - I found one in the Zig source:
// https://github.com/ziglang/zig/blob/041212a41cfaf029dc3eb9740467b721c76f406c/src/Compilation.zig#L2495
+//
+// 2) bbuccianti - I found one!
+// https://github.com/ziglang/zig/blob/master/lib/std/debug.zig#L477
+//
diff --git a/exercises/49_quiz6.zig b/exercises/049_quiz6.zig
index a1a1dec..a1a1dec 100644
--- a/exercises/49_quiz6.zig
+++ b/exercises/049_quiz6.zig
diff --git a/exercises/50_no_value.zig b/exercises/050_no_value.zig
index 8708d2d..8708d2d 100644
--- a/exercises/50_no_value.zig
+++ b/exercises/050_no_value.zig
diff --git a/exercises/51_values.zig b/exercises/051_values.zig
index dd68d3b..dd68d3b 100644
--- a/exercises/51_values.zig
+++ b/exercises/051_values.zig
diff --git a/exercises/052_slices.zig b/exercises/052_slices.zig
new file mode 100644
index 0000000..98177cd
--- /dev/null
+++ b/exercises/052_slices.zig
@@ -0,0 +1,49 @@
+//
+// We've seen that passing arrays around can be awkward. Perhaps you
+// remember a particularly horrendous function definition from quiz3?
+// This function can only take arrays that are exactly 4 items long!
+//
+// fn printPowersOfTwo(numbers: [4]u16) void { ... }
+//
+// That's the trouble with arrays - their size is part of the data
+// type and must be hard-coded into every usage of that type. This
+// digits array is a [10]u8 forever and ever:
+//
+// var digits = [10]u8{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+//
+// Thankfully, Zig has slices, which let you dynamically point to a
+// start item and provide a length. Here are slices of our digit
+// array:
+//
+// const foo = digits[0..1]; // 0
+// const bar = digits[3..9]; // 3 4 5 6 7 8
+// const all = digits[0..]; // 0 1 2 3 4 5 6 7 8 9
+//
+// As you can see, a slice [x..y] defines a first item by index x and
+// a length y (where y-1 is the index of the last item). Leaving y off
+// gives you the rest of the items.
+//
+// Notice that the type of a slice on an array of u8 items is []u8.
+//
+const std = @import("std");
+
+pub fn main() void {
+ var cards = [8]u8{ 'A', '4', 'K', '8', '5', '2', 'Q', 'J' };
+
+ // Please put the first 4 cards in hand1 and the rest in hand2.
+ const hand1: []u8 = cards[???];
+ const hand2: []u8 = cards[???];
+
+ std.debug.print("Hand1: ", .{});
+ printHand(hand1);
+
+ std.debug.print("Hand2: ", .{});
+ printHand(hand2);
+}
+
+// Please lend this function a hand. A u8 slice hand, that is.
+fn printHand(hand: ???) void {
+ for (hand) |h| {
+ std.debug.print("{u} ", .{h});
+ }
+}
diff --git a/exercises/053_slices2.zig b/exercises/053_slices2.zig
new file mode 100644
index 0000000..2456d86
--- /dev/null
+++ b/exercises/053_slices2.zig
@@ -0,0 +1,35 @@
+//
+// You are perhaps tempted to try slices on strings? They're arrays of
+// u8 characters after all, right? Slices on strings work great.
+// There's just one catch: don't forget that Zig string literals are
+// immutable (const) values. So we need to change the type of slice
+// from:
+//
+// var foo: []u8 = "foobar"[0..3];
+//
+// to:
+//
+// var foo: []const u8 = "foobar"[0..3];
+//
+// See if you can fix this Zero Wing-inspired phrase descrambler:
+const std = @import("std");
+
+pub fn main() void {
+ const scrambled = "great base for all your justice are belong to us";
+
+ const base1: []u8 = scrambled[15..23];
+ const base2: []u8 = scrambled[6..10];
+ const base3: []u8 = scrambled[32..];
+ printPhrase(base1, base2, base3);
+
+ const justice1: []u8 = scrambled[11..14];
+ const justice2: []u8 = scrambled[0..5];
+ const justice3: []u8 = scrambled[24..31];
+ printPhrase(justice1, justice2, justice3);
+
+ std.debug.print("\n", .{});
+}
+
+fn printPhrase(part1: []u8, part2: []u8, part3: []u8) void {
+ std.debug.print("'{s} {s} {s}.' ", .{part1, part2, part3});
+}
diff --git a/exercises/054_manypointers.zig b/exercises/054_manypointers.zig
new file mode 100644
index 0000000..23f2ae5
--- /dev/null
+++ b/exercises/054_manypointers.zig
@@ -0,0 +1,55 @@
+//
+// You can also make pointers to multiple items without using a slice.
+//
+// var foo: [4]u8 = [4]u8{ 1, 2, 3, 4 };
+// var foo_slice: []u8 = foo[0..];
+// var foo_ptr: [*]u8 = &foo;
+//
+// The difference between foo_slice and foo_ptr is that the slice has
+// a known length. The pointer doesn't. It is up to YOU to keep track
+// of the number of u8s foo_ptr points to!
+//
+const std = @import("std");
+
+pub fn main() void {
+ // Take a good look at the array type to which we're coercing
+ // the zen12 string (the REAL nature of strings will be
+ // revealed when we've learned some additional features):
+ const zen12: *const [21]u8 = "Memory is a resource.";
+ //
+ // It would also have been valid to coerce to a slice:
+ // const zen12: []const u8 = "...";
+ //
+ // Now let's turn this into a "many pointer":
+ const zen_manyptr: [*]const u8 = zen12;
+
+ // It's okay to access zen_manyptr just like an array or slice as
+ // long as you keep track of the length yourself!
+ //
+ // A "string" in Zig is a pointer to an array of const u8 values
+ // or a slice of const u8 values, into one, as we saw above). So,
+ // we could treat a "many pointer" of const u8 a string as long
+ // as we can CONVERT IT TO A SLICE. (Hint: we do know the length!)
+ //
+ // Please fix this line so the print below statement can print it:
+ const zen12_string: []const u8 = zen_manyptr;
+
+ // Here's the moment of truth!
+ std.debug.print("{s}\n", .{zen12_string});
+}
+//
+// Are all of these pointer types starting to get confusing?
+//
+// FREE ZIG POINTER CHEATSHEET! (Using u8 as the example type.)
+// +---------------+----------------------------------------------+
+// | u8 | one u8 |
+// | *u8 | pointer to one u8 |
+// | [2]u8 | two u8s |
+// | [*]u8 | pointer to unknown number of u8s |
+// | [2]const u8 | two immutable u8s |
+// | [*]const u8 | pointer to unknown number of immutable u8s |
+// | *[2]u8 | pointer to an array of 2 u8s |
+// | *const [2]u8 | pointer to an immutable array of 2 u8s |
+// | []u8 | slice of u8s |
+// | []const u8 | slice of immutable u8s |
+// +---------------+----------------------------------------------+
diff --git a/exercises/055_unions.zig b/exercises/055_unions.zig
new file mode 100644
index 0000000..5e08aa1
--- /dev/null
+++ b/exercises/055_unions.zig
@@ -0,0 +1,76 @@
+//
+// A union lets you store different types and sizes of data at
+// the same memory address. How is this possible? The compiler
+// sets aside enough memory for the largest thing you might want
+// to store.
+//
+// In this example, an instance of Foo always takes up u64 of
+// space memory even if you're currently storing a u8.
+//
+// const Foo = union {
+// small: u8,
+// medium: u32,
+// large: u64,
+// };
+//
+// The syntax looks just like a struct, but a Foo can only hold a
+// small OR a medium OR a large value. Once a field becomes
+// active, the other inactive fields cannot be accessed. To
+// change active fields, assign a whole new instance:
+//
+// var f = Foo{ .small = 5 };
+// f.small += 5; // OKAY
+// f.medium = 5432; // ERROR!
+// f = Foo{ .medium = 5432 }; // OKAY
+//
+// Unions can save space in memory because they let you "re-use"
+// a space in memory. They also provide a sort of primitive
+// polymorphism. Here fooBar() can take a Foo no matter what size
+// of unsigned integer it holds:
+//
+// fn fooBar(f: Foo) void { ... }
+//
+// Oh, but how does fooBar() know which field is active? Zig has
+// a neat way of keeping track, but for now, we'll just have to
+// do it manually.
+//
+// Let's see if we can get this program working!
+//
+const std = @import("std");
+
+// We've just started writing a simple ecosystem simulation.
+// Insects will be represented by either bees or ants. Bees store
+// the number of flowers they've visited that day and ants just
+// store whether or not they're still alive.
+const Insect = union {
+ flowers_visited: u16,
+ still_alive: bool,
+};
+
+// Since we need to specify the type of insect, we'll use an
+// enum (remember those?).
+const AntOrBee = enum { a, b };
+
+pub fn main() void {
+ // We'll just make one bee and one ant to test them out:
+ var ant = Insect{ .still_alive = true };
+ var bee = Insect{ .flowers_visited = 15 };
+
+ std.debug.print("Insect report! ", .{});
+
+ // Oops! We've made a mistake here.
+ printInsect(ant, AntOrBee.c);
+ printInsect(bee, AntOrBee.c);
+
+ std.debug.print("\n", .{});
+}
+
+// Eccentric Doctor Zoraptera says that we can only use one
+// function to print our insects. Doctor Z is small and sometimes
+// inscrutable but we do not question her.
+fn printInsect(insect: Insect, what_it_is: AntOrBee) void {
+ switch (what_it_is) {
+ .a => std.debug.print("Ant alive is: {}. ", .{insect.still_alive}),
+ .b => std.debug.print("Bee visited {} flowers. ", .{insect.flowers_visited}),
+ }
+}
diff --git a/exercises/056_unions2.zig b/exercises/056_unions2.zig
new file mode 100644
index 0000000..e4294db
--- /dev/null
+++ b/exercises/056_unions2.zig
@@ -0,0 +1,64 @@
+//
+// It is really quite inconvenient having to manually keep track
+// of the active field in our union, isn't it?
+//
+// Thankfully, Zig also has "tagged unions", which allow us to
+// store an enum value within our union representing which field
+// is active.
+//
+// const FooTag = enum{ small, medium, large };
+//
+// const Foo = union(FooTag) {
+// small: u8,
+// medium: u32,
+// large: u64,
+// };
+//
+// Now we can use a switch directly on the union to act on the
+// active field:
+//
+// var f = Foo{ .small = 10 };
+//
+// switch (f) {
+// .small => |my_small| do_something(my_small),
+// .medium => |my_medium| do_something(my_medium),
+// .large => |my_large| do_something(my_large),
+// }
+//
+// Let's make our Insects use a tagged union (Doctor Zoraptera
+// approves).
+//
+const std = @import("std");
+
+const InsectStat = enum { flowers_visited, still_alive };
+
+const Insect = union(InsectStat) {
+ flowers_visited: u16,
+ still_alive: bool,
+};
+
+pub fn main() void {
+ var ant = Insect{ .still_alive = true };
+ var bee = Insect{ .flowers_visited = 16 };
+
+ std.debug.print("Insect report! ", .{});
+
+ // Could it really be as simple as just passing the union?
+ printInsect(???);
+ printInsect(???);
+
+ std.debug.print("\n", .{});
+}
+
+fn printInsect(insect: Insect) void {
+ switch (???) {
+ .still_alive => |a| std.debug.print("Ant alive is: {}. ", .{a}),
+ .flowers_visited => |f| std.debug.print("Bee visited {} flowers. ", .{f}),
+ }
+}
+
+// By the way, did unions remind you of optional values and errors?
+// Optional values are basically "null unions" and errors use "error
+// union types". Now we can add our own unions to the mix to handle
+// whatever situations we might encounter:
+// union(Tag) { value: u32, toxic_ooze: void }
diff --git a/exercises/057_unions3.zig b/exercises/057_unions3.zig
new file mode 100644
index 0000000..142180f
--- /dev/null
+++ b/exercises/057_unions3.zig
@@ -0,0 +1,54 @@
+//
+// With tagged unions, it gets EVEN BETTER! If you don't have a
+// need for a separate enum, you can define an inferred enum with
+// your union all in one place. Just use the 'enum' keyword in
+// place of the tag type:
+//
+// const Foo = union(enum) {
+// small: u8,
+// medium: u32,
+// large: u64,
+// };
+//
+// Let's convert Insect. Doctor Zoraptera has already deleted the
+// explicit InsectStat enum for you!
+//
+const std = @import("std");
+
+const Insect = union(InsectStat) {
+ flowers_visited: u16,
+ still_alive: bool,
+};
+
+pub fn main() void {
+ var ant = Insect{ .still_alive = true };
+ var bee = Insect{ .flowers_visited = 17 };
+
+ std.debug.print("Insect report! ", .{});
+
+ printInsect(ant);
+ printInsect(bee);
+
+ std.debug.print("\n", .{});
+}
+
+fn printInsect(insect: Insect) void {
+ switch (insect) {
+ .still_alive => |a| std.debug.print("Ant alive is: {}. ", .{a}),
+ .flowers_visited => |f| std.debug.print("Bee visited {} flowers. ", .{f}),
+ }
+}
+
+// Inferred enums are neat, representing the tip of the iceberg
+// in the relationship between enums and unions. You can actually
+// coerce a union TO an enum (which gives you the active field
+// from the union as an enum). What's even wilder is that you can
+// coerce an enum to a union! But don't get too excited, that
+// only works when the union type is one of those weird zero-bit
+// types like void!
+//
+// Tagged unions, as with most ideas in computer science, have a
+// long history going back to the 1960s. However, they're only
+// recently becoming mainstream, particularly in system-level
+// programming languages. You might have also seen them called
+// "variants", "sum types", or even "enums"!