about summary refs log tree commit diff
path: root/lang/zig/if.zig
blob: 99de2b5cb05580c141ec227562e4bc27f7b8db59 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// If expressions have three uses, corresponding to the three types:
// * bool
// * ?T
// * anyerror!T

const expect = @import("std").testing.expect;

test "if expression" {
    // If expressions are used instead of a ternary expression.
    const a: u32 = 5;
    const b: u32 = 4;
    const result = if (a != b) 47 else 3089;
    expect(result == 47);
}

test "if boolean" {
    // If expressions test boolean conditions.
    const a: u32 = 5;
    const b: u32 = 4;
    if (a != b) {
        expect(true);
    } else if (a == 9) {
        unreachable;
    } else {
        unreachable;
    }
}

// If expressions test for null.
test "if optional" {
    if (@as(?u32, 0)) |value| {
        expect(value == 0);
    } else {
        unreachable;
    }

    const b: ?u32 = null;
    if (b) |value| {
        unreachable;
    } else {
        expect(true);
    }
    // To test against null only, use the binary equality operator.
    if (b == null)
        expect(true);

    // Access the value by reference using a pointer capture.
    var c: ?u32 = 3;
    if (c) |*value|
        value.* = 2;
    // The else is not required.
    if (c) |value|
        expect(value == 2);
}

// If expressions test for errors.  Note the |err| capture on the else.
test "if error union" {
    const a: anyerror!u32 = 0;
    if (a) |value| {
        expect(value == 0);
    } else |err| {
        unreachable;
    }

    const b: anyerror!u32 = error.BadValue;
    if (b) |value| {
        unreachable;
    } else |err| {
        expect(err == error.BadValue);
    }

    // The else and |err| capture is strictly required.
    if (a) |value| {
        expect(value == 0);
    } else |_| {}

    // To check only the error value, use an empty block expression.
    if (b) |_| {} else |err| {
        expect(err == error.BadValue);
    }

    // Access the value by reference using a pointer capture.
    var c: anyerror!u32 = 3;
    if (c) |*value| {
        value.* = 9;
    } else |err| {
        unreachable;
    }

    if (c) |value| {
        expect(value == 9);
    } else |err| {
        unreachable;
    }
}

// If expressions test for errors before unwrapping optionals.
// The |optional_value| capture's type is ?u32.
test "if error union with optional" {
    const a: anyerror!?u32 = 0;
    if (a) |optional_value| {
        expect(optional_value.? == 0);
    } else |err| {
        unreachable;
    }

    const b: anyerror!?u32 = null;
    if (b) |optional_value| {
        expect(optional_value == null);
    } else |err| {
        unreachable;
    }
    if (b) |*optional_value| {
        if (optional_value.*) |_|
            unreachable;
    } else |err| {
        unreachable;
    }

    const c: anyerror!?u32 = error.BadValue;
    if (c) |optional_value| {
        unreachable;
    } else |err| {
        expect(err == error.BadValue);
    }

    // Access the value by reference by using a pointer capture each time.
    var d: anyerror!?u32 = 3;
    if (d) |*optional_value| {
        if (optional_value.*) |*value| {
            value.* = 9;
        }
    } else |err| {
        unreachable;
    }
    if (d) |optional_value| {
        expect(optional_value.? == 9);
    } else |err| {
        unreachable;
    }
}