From 6ad9774189fbd64b2f2c9519f4513ab34b0c3809 Mon Sep 17 00:00:00 2001 From: Dave Gauer Date: Fri, 12 Mar 2021 18:59:46 -0500 Subject: "999 is enough for anybody" triple-zero padding (#18) When I hit 999 exercises, I will finally have reached the ultimate state of soteriological release and no more exercises will be needed. The cycle will be complete. All that will be left is perfect quietude, freedom, and highest happiness. --- exercises/055_unions.zig | 76 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 exercises/055_unions.zig (limited to 'exercises/055_unions.zig') 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}), + } +} -- cgit v1.2.3-ZIG