switch

switch.zig

  1. const assert = @import("std").debug.assert;
  2. const builtin = @import("builtin");
  3. test "switch simple" {
  4. const a: u64 = 10;
  5. const zz: u64 = 103;
  6. // All branches of a switch expression must be able to be coerced to a
  7. // common type.
  8. //
  9. // Branches cannot fallthrough. If fallthrough behavior is desired, combine
  10. // the cases and use an if.
  11. const b = switch (a) {
  12. // Multiple cases can be combined via a ','
  13. 1, 2, 3 => 0,
  14. // Ranges can be specified using the ... syntax. These are inclusive
  15. // both ends.
  16. 5...100 => 1,
  17. // Branches can be arbitrarily complex.
  18. 101 => blk: {
  19. const c: u64 = 5;
  20. break :blk c * 2 + 1;
  21. },
  22. // Switching on arbitrary expressions is allowed as long as the
  23. // expression is known at compile-time.
  24. zz => zz,
  25. comptime blk: {
  26. const d: u32 = 5;
  27. const e: u32 = 100;
  28. break :blk d + e;
  29. } => 107,
  30. // The else branch catches everything not already captured.
  31. // Else branches are mandatory unless the entire range of values
  32. // is handled.
  33. else => 9,
  34. };
  35. assert(b == 1);
  36. }
  37. // Switch expressions can be used outside a function:
  38. const os_msg = switch (builtin.os) {
  39. builtin.Os.linux => "we found a linux user",
  40. else => "not a linux user",
  41. };
  42. // Inside a function, switch statements implicitly are compile-time
  43. // evaluated if the target expression is compile-time known.
  44. test "switch inside function" {
  45. switch (builtin.os) {
  46. builtin.Os.fuchsia => {
  47. // On an OS other than fuchsia, block is not even analyzed,
  48. // so this compile error is not triggered.
  49. // On fuchsia this compile error would be triggered.
  50. @compileError("fuchsia not supported");
  51. },
  52. else => {},
  53. }
  54. }
  1. $ zig test switch.zig
  2. Test 1/2 switch simple...OK
  3. Test 2/2 switch inside function...OK
  4. All tests passed.

switch can be used to capture the field values of a Tagged union. Modifications to the field values can be done by placing a * before the capture variable name, turning it into a pointer.

test.zig

  1. const assert = @import("std").debug.assert;
  2. test "switch on tagged union" {
  3. const Point = struct {
  4. x: u8,
  5. y: u8,
  6. };
  7. const Item = union(enum) {
  8. A: u32,
  9. C: Point,
  10. D,
  11. };
  12. var a = Item{ .C = Point{ .x = 1, .y = 2 } };
  13. // Switching on more complex enums is allowed.
  14. const b = switch (a) {
  15. // A capture group is allowed on a match, and will return the enum
  16. // value matched.
  17. Item.A => |item| item,
  18. // A reference to the matched value can be obtained using `*` syntax.
  19. Item.C => |*item| blk: {
  20. item.*.x += 1;
  21. break :blk 6;
  22. },
  23. // No else is required if the types cases was exhaustively handled
  24. Item.D => 8,
  25. };
  26. assert(b == 6);
  27. assert(a.C.x == 2);
  28. }
  1. $ zig test test.zig
  2. Test 1/1 switch on tagged union...OK
  3. All tests passed.

See also: