switch

switch.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  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. expect(b == 1);
  36. }
  37. // Switch expressions can be used outside a function:
  38. const os_msg = switch (std.Target.current.os.tag) {
  39. .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 (std.Target.current.os.tag) {
  46. .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. 1/2 test "switch simple"... OK
  3. 2/2 test "switch inside function"... OK
  4. All 2 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 expect = @import("std").testing.expect;
  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. e: u32,
  12. };
  13. var a = Item{ .c = Point{ .x = 1, .y = 2 } };
  14. // Switching on more complex enums is allowed.
  15. const b = switch (a) {
  16. // A capture group is allowed on a match, and will return the enum
  17. // value matched. If the payload types of both cases are the same
  18. // they can be put into the same switch prong.
  19. Item.a, Item.e => |item| item,
  20. // A reference to the matched value can be obtained using `*` syntax.
  21. Item.c => |*item| blk: {
  22. item.*.x += 1;
  23. break :blk 6;
  24. },
  25. // No else is required if the types cases was exhaustively handled
  26. Item.d => 8,
  27. };
  28. expect(b == 6);
  29. expect(a.c.x == 2);
  30. }
  1. $ zig test test.zig
  2. 1/1 test "switch on tagged union"... OK
  3. All 1 tests passed.

See also:

Exhaustive Switching

When a switch expression does not have an else clause, it must exhaustively list all the possible values. Failure to do so is a compile error:

test.zig

  1. const Color = enum {
  2. auto,
  3. off,
  4. on,
  5. };
  6. test "exhaustive switching" {
  7. const color = Color.off;
  8. switch (color) {
  9. Color.auto => {},
  10. Color.on => {},
  11. }
  12. }
  1. $ zig test test.zig
  2. ./docgen_tmp/test.zig:9:5: error: enumeration value 'Color.off' not handled in switch
  3. switch (color) {
  4. ^
  5. ./docgen_tmp/test.zig:7:29: note: referenced here
  6. test "exhaustive switching" {
  7. ^

Switching with Enum Literals

Enum Literals can be useful to use with switch to avoid repetitively specifying enum or union types:

test.zig

  1. const std = @import("std");
  2. const expect = std.testing.expect;
  3. const Color = enum {
  4. auto,
  5. off,
  6. on,
  7. };
  8. test "enum literals with switch" {
  9. const color = Color.off;
  10. const result = switch (color) {
  11. .auto => false,
  12. .on => false,
  13. .off => true,
  14. };
  15. expect(result);
  16. }
  1. $ zig test test.zig
  2. 1/1 test "enum literals with switch"... OK
  3. All 1 tests passed.