12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- //
- // 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}),
- }
- }
|