We cannot have local var names inside a struct function that are equal to a field in that struct.
Mostly that is strange because we always have to access that field with self.xxx.
So is that restriction only because of the phenomenon “files are structs”?
(In that case we have no thisfile.xxx)
The absence of identifier shadowing in Zig seems to be more a decision to improve readability than anything else. Zig guarantees that an identifier, once declared in a scope, always refers to the same object in that scope and all of its descendant scopes. Moreover, it’s been decided that declarations and fields share the same namespace, to allow for decl literals (the thing where you can call .init() and it infers the namespace from the result type).
I don’t think there is anything technically preventing Zig from supporting shadowing of identifiers. It was a purposeful decision to not allow it.
Actually we can. What is not possible is having local variables with the same name as global variables namespaced in the struct, because these are accessed without self.xxx.
const S = struct {
field: i32,
var global: i32 = 3;
pub fn func(self: *S) void {
self.field = 5; // accesses the struct field
var field: i32 = 42; // no problem
global = 13; // accesses the global variable
var global = 12; // ERROR
}
};
See, this is where the argument breaks down for me. Every single time I try to shadow, it’s intentional. In fact, it usually prevents future errors, because it narrows down the scope of things. And I’m too old and stupid to deal with wide scopes of things.
In languages that allow shadowing I try to to use it to immediately eliminate a no-longer-necessary variable from the namespace:
const path = "file path";
const aw_wtf = std.path.windowsParsePath(path);
// oh gosh, I sure like having `path` still available in my namespace
std.fs.whatever(pa^H^Haw_wtf);