mirror of
https://codeberg.org/andyscott/ziglings.git
synced 2024-12-22 14:03:10 -05:00
add ex 55 unions
This commit is contained in:
parent
784b66ffcf
commit
7b1c9c3b63
4 changed files with 87 additions and 1 deletions
|
@ -130,7 +130,7 @@ Planned exercises:
|
||||||
* [x] Struct methods
|
* [x] Struct methods
|
||||||
* [x] Slices
|
* [x] Slices
|
||||||
* [x] Many pointers
|
* [x] Many pointers
|
||||||
* [ ] Unions
|
* [x] Unions
|
||||||
* [ ] Numeric types (integers, floats)
|
* [ ] Numeric types (integers, floats)
|
||||||
* [ ] Labelled blocks and loops
|
* [ ] Labelled blocks and loops
|
||||||
* [ ] Loops as expressions
|
* [ ] Loops as expressions
|
||||||
|
|
|
@ -280,6 +280,10 @@ const exercises = [_]Exercise{
|
||||||
.main_file = "54_manypointers.zig",
|
.main_file = "54_manypointers.zig",
|
||||||
.output = "Memory is a resource.",
|
.output = "Memory is a resource.",
|
||||||
},
|
},
|
||||||
|
.{
|
||||||
|
.main_file = "55_unions.zig",
|
||||||
|
.output = "Insect report! Ant alive is: true. Bee visited 15 flowers.",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Check the zig version to make sure it can compile the examples properly.
|
/// Check the zig version to make sure it can compile the examples properly.
|
||||||
|
|
76
exercises/55_unions.zig
Normal file
76
exercises/55_unions.zig
Normal file
|
@ -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}),
|
||||||
|
}
|
||||||
|
}
|
6
patches/patches/55_unions.patch
Normal file
6
patches/patches/55_unions.patch
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
62,63c62,63
|
||||||
|
< printInsect(ant, AntOrBee.c);
|
||||||
|
< printInsect(bee, AntOrBee.c);
|
||||||
|
---
|
||||||
|
> printInsect(ant, AntOrBee.a);
|
||||||
|
> printInsect(bee, AntOrBee.b);
|
Loading…
Reference in a new issue