Having strong backwards compatibility does that to the language, alternative is arguably worse (see Python 2 vs 3).
---
Problem is lots of implementation things are vying for inclusion. And many thing people want aren't safe or block/are blocked by possible future changes.
For example default/named arguments were blocked by ambiguity in parsing when it comes to type ascription iirc. And not having default arguments makes adding allocator quite more cumbersome.
Plus Rust maintainers are seeing some common patterns and are trying to abstract over them - like keyword generics/ effect system. If they don't hit right abstraction now, things will be much more harder later. If they over abstract, its extremly hard to remove it.
?!!??u32 is a perfectly cromulent type in Zig.
const std = @import("std");
fn some(x: anytype) ?@TypeOf(x) {
return x;
}
fn print_my_guy(maybe_maybe_x: ??u32) void {
if(maybe_maybe_x) |maybe_x| {
if (maybe_x) |x| {
std.debug.print("that's Some(Some({d})) {any}\n", .{x, maybe_maybe_x});
} else {
std.debug.print("that's Some(None) {any}\n", .{maybe_maybe_x});
}
} else {
std.debug.print("that's None {any}\n", .{maybe_maybe_x});
}
}
pub fn main() void {
const a: ??u32 = 5;
const b: ??u32 = null;
const c: ??u32 = some(@as(?u32, null));
print_my_guy(a);
print_my_guy(b);
print_my_guy(c);
} const std = @import("std") ;
const print = std.debug.print ;
pub fn main() void {
const simple_none : ?u8 = null ;
const double_optional_none : ??u8 = null ;
const double_optional_some_none : ??u8 = simple_none ;
print("none equals some none: {}", .{ double_optional_none == double_optional_some_none });
// prints none equals some none: false
}
This is an oxymoron :) The strictness and borrow checker are part of the power and modernity of Rust.
But even apart from that, Rust has automatic value-based destructors (destructor follows the value as it's moved across scopes and is only called in the final scope), whereas Zig only has scope-based destructors (defer) and you need to remember to write them and ensure they're called exactly once per value. Rust has properly composable Option/Result monads, whereas Zig has special-cased ! and ? which don't compose but do benefit from nice syntax due to their special-cased-ness.
Of course from Zig's point-of-view these are features, not deficiences, which is completely understandable given what kind of language it wants to be. And the other advantages you listed like comptime (Rust's const-eval is very constrained and has been WIP for ages) and custom allocator support from day 1 (the way Rust is bolting it on will make most existing code unusable with custom allocators, including parts of Rust's own standard library) are indeed good advantages. Zig also has very nice syntax unification - generic types are type constructor functions, modules are structs, etc.
I hope that one day we'll have a language that combines the best of Rust's strictness and Zig's comptime and syntax.