about summary refs log tree commit diff
path: root/lang/zig/union-tag.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lang/zig/union-tag.zig')
-rw-r--r--lang/zig/union-tag.zig68
1 files changed, 68 insertions, 0 deletions
diff --git a/lang/zig/union-tag.zig b/lang/zig/union-tag.zig
new file mode 100644
index 0000000..6954c73
--- /dev/null
+++ b/lang/zig/union-tag.zig
@@ -0,0 +1,68 @@
+const eql = std.mem.eql;
+const expect = std.testing.expect;
+const std = @import("std");
+
+const ComplexTypeTag = enum { ok, not_ok };
+const ComplexType = union(ComplexTypeTag) { ok: u8, not_ok: void };
+
+test "switch on tagged union" {
+    const c = ComplexType{ .ok = 42 };
+    expect(@as(ComplexTypeTag, c) == ComplexTypeTag.ok);
+
+    switch (c) {
+        ComplexTypeTag.ok => |value| expect(value == 42),
+        ComplexTypeTag.not_ok => unreachable,
+    }
+}
+
+test "@TagType" {
+    expect(@TagType(ComplexType) == ComplexTypeTag);
+}
+
+test "coerce to enum" {
+    const c1: ComplexType = ComplexType{ .ok = 42 };
+    const c2: ComplexTypeTag = ComplexType.not_ok;
+    expect(c1 == .ok);
+    expect(c2 == .not_ok);
+}
+
+test "modify tagged union in switch" {
+    var c = ComplexType{ .ok = 42 };
+    expect(c == .ok);
+
+    switch (c) {
+        ComplexTypeTag.ok => |*value| value.* += 1,
+        ComplexTypeTag.not_ok => unreachable,
+    }
+
+    expect(c.ok == 43);
+}
+
+const Variant = union(enum) {
+    int: i32,
+    boolean: bool,
+
+    // void can be omitted when inferring enum tag type.
+    none,
+
+    fn truthy(self: Variant) bool {
+        return switch (self) {
+            Variant.int => |x_int| x_int != 0,
+            Variant.boolean => |x_bool| x_bool,
+            Variant.none => false,
+        };
+    }
+};
+
+test "union method" {
+    var v1 = Variant{ .int = 420 };
+    var v2 = Variant{ .boolean = false };
+
+    expect(v1.truthy());
+    expect(!v2.truthy());
+}
+
+const Small2 = union(enum) { a: i32, b: bool, c: u8 };
+test "@tagName" {
+    expect(eql(u8, @tagName(Small2.a), "a"));
+}