Zig NEWS

Discussion on: Sneaky Error Payloads

Collapse
 
danielchasehooper profile image
Daniel Hooper

I don't see what the compile time reflection gets you here. The same thing can be accomplished more simply with an optional pointer.

const std = @import("std");

const CustomError = error{NumberError};

const NumberErrorPayload = struct {
message: []const u8 = undefined,
value: u64 = undefined,
};

pub fn raise(message: []const u8, value: u64, out_error: ?*NumberErrorPayload) CustomError {
if (out_error) |opts|{
opts.message = message;
opts.value = value;
}
return CustomError.NumberError;
}

fn add_one(number: u64, out_error: ?*NumberErrorPayload) CustomError!u64 {
if (number == 42) {
return raise("bad number encountered", number, out_error);
} else {
return number + 1;
}
}

pub fn main() !void {
std.debug.print("no error: {}\n", .{try add_one(1, null)});

_ = add_one(42, null) catch trap1: {
    std.debug.print("errored without payload! \n", .{});
    // we need this to have a matching return type
    break :trap1 0;
};

var payload = NumberErrorPayload{};

std.debug.print("no error: .{}\n", .{try add_one(1, &payload)});

_ = add_one(42, &payload) catch trap2: {
    std.debug.print("errored with payload: {s}, value {}! \n", .{ payload.message, payload.value });
    break :trap2 0;
};
Enter fullscreen mode Exit fullscreen mode

}

Collapse
 
ityonemo profile image
Isaac Yonemoto • Edited

You're checking the out_error for nullity every time you call the function.

Having said that, the optional parameter works nicely too, and (this is a matter of taste, I suppose) easier to read in the case you don't have other parameter options.