From dff61673c8e5278ec7c0b0065327ebe2351d00ee Mon Sep 17 00:00:00 2001 From: Dave Gauer Date: Tue, 9 Mar 2021 20:51:00 -0500 Subject: [PATCH] add ex56 for real --- build.zig | 4 +++ exercises/56_unions2.zig | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 exercises/56_unions2.zig diff --git a/build.zig b/build.zig index 35f00a1..e8e160e 100644 --- a/build.zig +++ b/build.zig @@ -284,6 +284,10 @@ const exercises = [_]Exercise{ .main_file = "55_unions.zig", .output = "Insect report! Ant alive is: true. Bee visited 15 flowers.", }, + .{ + .main_file = "56_unions2.zig", + .output = "Insect report! Ant alive is: true. Bee visited 16 flowers.", + }, }; /// Check the zig version to make sure it can compile the examples properly. diff --git a/exercises/56_unions2.zig b/exercises/56_unions2.zig new file mode 100644 index 0000000..e4294db --- /dev/null +++ b/exercises/56_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 }