055_unions.zig 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //
  2. // A union lets you store different types and sizes of data at
  3. // the same memory address. How is this possible? The compiler
  4. // sets aside enough memory for the largest thing you might want
  5. // to store.
  6. //
  7. // In this example, an instance of Foo always takes up u64 of
  8. // space in memory even if you're currently storing a u8.
  9. //
  10. // const Foo = union {
  11. // small: u8,
  12. // medium: u32,
  13. // large: u64,
  14. // };
  15. //
  16. // The syntax looks just like a struct, but a Foo can only hold a
  17. // small OR a medium OR a large value. Once a field becomes
  18. // active, the other inactive fields cannot be accessed. To
  19. // change active fields, assign a whole new instance:
  20. //
  21. // var f = Foo{ .small = 5 };
  22. // f.small += 5; // OKAY
  23. // f.medium = 5432; // ERROR!
  24. // f = Foo{ .medium = 5432 }; // OKAY
  25. //
  26. // Unions can save space in memory because they let you "re-use"
  27. // a space in memory. They also provide a sort of primitive
  28. // polymorphism. Here fooBar() can take a Foo no matter what size
  29. // of unsigned integer it holds:
  30. //
  31. // fn fooBar(f: Foo) void { ... }
  32. //
  33. // Oh, but how does fooBar() know which field is active? Zig has
  34. // a neat way of keeping track, but for now, we'll just have to
  35. // do it manually.
  36. //
  37. // Let's see if we can get this program working!
  38. //
  39. const std = @import("std");
  40. // We've just started writing a simple ecosystem simulation.
  41. // Insects will be represented by either bees or ants. Bees store
  42. // the number of flowers they've visited that day and ants just
  43. // store whether or not they're still alive.
  44. const Insect = union {
  45. flowers_visited: u16,
  46. still_alive: bool,
  47. };
  48. // Since we need to specify the type of insect, we'll use an
  49. // enum (remember those?).
  50. const AntOrBee = enum { a, b };
  51. pub fn main() void {
  52. // We'll just make one bee and one ant to test them out:
  53. var ant = Insect{ .still_alive = true };
  54. var bee = Insect{ .flowers_visited = 15 };
  55. std.debug.print("Insect report! ", .{});
  56. // Oops! We've made a mistake here.
  57. printInsect(ant, AntOrBee.c);
  58. printInsect(bee, AntOrBee.c);
  59. std.debug.print("\n", .{});
  60. }
  61. // Eccentric Doctor Zoraptera says that we can only use one
  62. // function to print our insects. Doctor Z is small and sometimes
  63. // inscrutable but we do not question her.
  64. fn printInsect(insect: Insect, what_it_is: AntOrBee) void {
  65. switch (what_it_is) {
  66. .a => std.debug.print("Ant alive is: {}. ", .{insect.still_alive}),
  67. .b => std.debug.print("Bee visited {} flowers. ", .{insect.flowers_visited}),
  68. }
  69. }