Zig Optionals
An optional is a value that may hold a payload of a type or may hold null. It makes the missing-value case explicit instead of hiding it in a special number.
Capture a present value and skip a missing one
An if capture runs its block for a present value. It runs the else block for null.
const std = @import("std");
pub fn main() !void {
const out = std.io.getStdOut().writer();
const a: ?i32 = 7;
const b: ?i32 = null;
if (a) |v| {
try out.print("{d}\n", .{v});
} else {
try out.print("none\n", .{});
}
if (b) |v| {
try out.print("{d}\n", .{v});
} else {
try out.print("none\n", .{});
}
}
Fill a default and unwrap a present value
orelse replaces null with 0 here. The .? unwrap reads the payload of a value that is present.
const std = @import("std");
pub fn main() !void {
const out = std.io.getStdOut().writer();
const missing: ?i32 = null;
const present: ?i32 = 9;
try out.print("{d} {d}\n", .{ missing orelse 0, present.? });
}
Loop while a value is present
A while capture runs while the optional holds a value. Setting it to null after 1 ends the loop.
const std = @import("std");
pub fn main() !void {
const out = std.io.getStdOut().writer();
var opt: ?i32 = 3;
while (opt) |v| {
try out.print("{d}\n", .{v});
if (v == 1) {
opt = null;
} else {
opt = v - 1;
}
}
}
Example
const std = @import("std");
pub fn main() !void {
const out = std.io.getStdOut().writer();
const word: []const u8 = "zigzag";
const hit = std.mem.indexOf(u8, word, "zag");
const miss = std.mem.indexOf(u8, word, "sun");
if (hit) |i| {
try out.print("{d} {s}\n", .{ i, word[i..] });
} else {
try out.print("miss\n", .{});
}
try out.print("{d}\n", .{miss orelse 99});
}
Key points
- Optional: ?i32 is a type that holds an i32 value or null.
- Null: null means no value is present.
- Capture: if (opt) |v| runs only when a value is present and names it v.
- Default: opt orelse 0 gives 0 when opt is null.
- Unwrap: opt.? gives the payload when a value is present.
- Loop: while (opt) |v| repeats while a value is present and names each payload v.
In this example, indexOf finds zag at index 3, so the if capture prints that index and the text starting there. The search for sun returns null, so orelse supplies 99 for the second line. Later lessons pair this choice with errors, which report why something failed.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
What does (x orelse 5) give when x is a ?i32 holding null?