diff options
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.zig | 49 | ||||
-rw-r--r-- | exercises/053_slices2.zig | 35 | ||||
-rw-r--r-- | exercises/054_manypointers.zig | 55 | ||||
-rw-r--r-- | exercises/055_unions.zig | 76 | ||||
-rw-r--r-- | exercises/056_unions2.zig | 64 | ||||
-rw-r--r-- | exercises/057_unions3.zig | 54 |
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"! |