| I've been writing a fair bit since a few months ago, and have written a few
things for the stdlib. Here are some examples I like about it. Hassle-free error management Consider you write a function fn div(a: u8, b: u8) -> u8 {
a / b
}
If later you find an error case that needs to be handled updating the code
usually will not require much extra addition. error DivideByZero;
fn div(a: u8, b: u8) -> %u8 {
if (b == 0) {
error.divideByZero
} else {
a / b
}
}
The caller can choose to ignore errors using `%%div(5, 1)` or can propagate
errors to the caller, similar to Rust's `try!`, `?` using `%return div(5, 2)`.I find this so easy that I'm much more inclined to think about edge cases and
handle errors up front. I find when writing Rust the extra setup and management
of errors adds a fair bit of tedium (although to be fair, with error-chain and
proper setup at the beginning of a project this isn't too bad). Compile-time programming Zig has pretty strong compile-time programming support. For example, its printf
formatting capability is all written in userland code [1]. It doesn't at this
moment support code-generation like D's mixins but I personally have not found
this too problematic. Generic functions can be written in a duck-typing fashion. With compile-time
assertions the inputs can be limited to what they need pretty clearly and the
errors during usage are pretty self-explanatory. error Overflow;
pub fn absInt(x: var) -> %@typeOf(x) {
const T = @typeOf(x);
comptime assert(@typeId(T) == builtin.TypeId.Int); // must pass an integer to absInt
comptime assert(T.is_signed); // must pass a signed integer to absInt
if (x == @minValue(@typeOf(x))) {
return error.Overflow;
} else {
@setDebugSafety(this, false);
return if (x < 0) -x else x;
}
}
Zig doesn't have any form of macros. Everything is done in the language itself.[1]: http://ziglang.org/documentation/#case-study-printf |
>I find this so easy that I'm much more inclined to think about edge cases and handle errors up front. I find when writing Rust the extra setup and management of errors adds a fair bit of tedium (although to be fair, with error-chain and proper setup at the beginning of a project this isn't too bad).
How is this different than say:
That unwrap() is performing the same thing as your %% example, if I understand it correctly.Are the Error types in Zig on the stack or the heap? By default Rust puts everything, including errors, on the stack, which means that the size of the return type always needs to be known. To make this easier you can return Boxed errors:
And then error types can be very simple. Also, I recommend people getting into Rust really checkout error_chain!, which is a macro that helps in combining all the errors that your library might need to deal with: https://docs.rs/error-chain/0.11.0/error_chain/