about summary refs log tree commit diff
path: root/lang/zig/defer.zig
diff options
context:
space:
mode:
Diffstat (limited to 'lang/zig/defer.zig')
-rw-r--r--lang/zig/defer.zig62
1 files changed, 62 insertions, 0 deletions
diff --git a/lang/zig/defer.zig b/lang/zig/defer.zig
new file mode 100644
index 0000000..754b3af
--- /dev/null
+++ b/lang/zig/defer.zig
@@ -0,0 +1,62 @@
+const std = @import("std");
+const expect = std.testing.expect;
+const print = std.debug.print;
+
+// defer will execute an expression at the end of the current scope.
+fn deferExample() usize {
+    var a: usize = 1;
+
+    {
+        defer a = 2;
+        a = 1;
+    }
+    expect(a == 2);
+
+    a = 5;
+    return a;
+}
+
+test "defer basics" {
+    expect(deferExample() == 5);
+}
+
+// If multiple defer statements are specified, they will be executed in
+// the reverse order they were run.
+fn deferUnwindExample() void {
+    print("\n", .{});
+
+    defer print("1 ", .{});
+    defer print("2 ", .{});
+    // defers are not run if they are never executed.
+    if (false) {
+        defer print("3 ", .{});
+    }
+    // somehow this isn't a scope though?
+    if (true) {
+        defer print("4 ", .{});
+    }
+}
+
+test "defer unwinding" {
+    deferUnwindExample();
+    print("\n", .{});
+}
+
+// The errdefer keyword is similar to defer,
+// but will only execute if the scope returns with an error.
+//
+// This is especially useful in allowing a function to clean up properly
+// on error, and replaces goto error handling tactics as seen in C.
+fn deferErrorExample(is_error: bool) !void {
+    print("\nstart of function\n", .{});
+    // This will always be executed on exit
+    defer print("end of function\n", .{});
+    errdefer print("encountered an error!\n", .{});
+    if (is_error)
+        return error.DeferError;
+}
+
+test "errdefer unwinding" {
+    deferErrorExample(false) catch {};
+    deferErrorExample(true) catch {};
+}