Hacker News new | ask | show | jobs
by chrisco255 498 days ago
They're really just enum variants. You can easily capture the error and conditionally handle it:

fn failFn() error{Oops}!i32 { try failingFunction(); return 12; }

test "try" { const v = failFn() catch |err| { try expect(err == error.Oops); return; }; try expect(v == 12); // is never reached }

1 comments

> You can easily capture the error and conditionally handle it

Sure. But the compiler won't help you check that your function only throws the errors that you think it does, or that your try block is handling all the errors that can be thrown inside it.

> ...the compiler won't help you check that your function only throws the errors that you think it does, or that your try block is handling all the errors that can be thrown inside it.

It will do both of those:

    const std = @import("std");

    fn throws(i: usize) !void {
        return switch (i) {
            0 => error.zero,
            1 => error.one,
            else => error.many,
        };
    }

    fn catches(i: usize) !void {
        throws(i) catch |err| {
            return switch (err) {
                error.one => error.uno,
                else => |other| other,
            };
        };
    }

    pub fn main() void {
        catches(std.os.argv.len) catch |err| {
            switch (err) {
                // Type error if you comment out any of these:
                // note: unhandled error value: 'error.zero'
                error.zero => std.debug.print("0\n", .{}),
                error.uno => std.debug.print("1\n", .{}),
                error.many => std.debug.print("2\n", .{}),
                // Type error if you uncomment this:
                // 'error.one' not a member of destination error set
                //error.one => std.debug.print("1\n", .{}),
            }
        };
    }
It wouldn't hurt to just read the docs before making confident claims.