Open
Description
Sometimes it would be useful to handle errors by switching on groups (sets) at a time. I imagine this might especially come in handy when dealing with third party libraries whose functions categorize errors into sets. This feature would keep code a tiny bit more robust against library upgrades: If that third party library extended one of the error sets it returns, your code would still be handling errors of the same "category" with your existing switch prong.
Let's make believe for a moment:
main.zig
const warn = @import("std").debug.warn;
const http = @import("http.zig");
pub fn main() void {
const res = http.doRequest() catch |err| switch (err) {
http.ClientError => |e| warn("we goofed: {}\n", e), // error set + payload
http.ServerError => |_| warn("they goofed\n"), // error set, discard payload
error.OutOfMemory => warn("{\n}", err), // error
else => unreachable, // else
};
warn("response: {}\n", res);
}
http.zig
pub fn doRequest() (ClientError || ServerError || error{OutOfMemory})![]const u8 {
return ServerError.NotImplemented;
}
pub const ClientError = error{
BadRequest,
Unauthorized,
Forbidden,
NotFound,
};
pub const ServerError = error{
InternalError,
NotImplemented,
ServiceUnavailable,
};
Present-day (0.4.0+dbb5da14
), running zig build-exe main.zig
gives:
error: expected type 'error{BadRequest,Unauthorized,Forbidden,NotFound,InternalError,NotImplemented,ServiceUnavailable,OutOfMemory,}', found 'type'
http.ClientError => |e| warn("we goofed: {}\n", e), // error set + payload
^
Notes
- Slightly related: else value when switching on error set should have optional capture value which is subset #769
- This proposal originated from a desire in this real-world block:
Lines 55 to 65 in 063d05a
- The payload in this proposal might be completely superfluous given the current design of errors. The above code could use the outer capture
err
just as well as the prong capturee
, since there's nothing to unwrap. (This would not be the case if error sets were unique container values unto themselves rather than global sets -- a separate discussion.) - Interesting bonus that we'd get for free, for what it's worth: anonymous error sets as a prong. Not like that's more useful than a comma-separated multi-case prong -- just a nice example of how Zig's elegant syntax design allows for all sorts of expressions.
switch (err) {
error{Evil, OutOfMemory} => |e| warn("very bad: {}\n", e),
else => {},
}