| > If you want to make pointers not have a nil state by default, this requires one of two possibilities: requiring the programmer to test every pointer on use, or assume pointers cannot be nil. The former is really annoying, and the latter requires [...] explicit initialization of every value everywhere. I used to be an "initialize everything" partisan, but meaningful zero-values have grown on me. I still don't think everything should be zero-initialized, though (that is, valid when initialized to zero). I'd prefer it if there were a two-colour system where a type is only zero-initialized if it don't contain a pointer, either directly or transiently. The trick would be that zero-initialized sum types have a default variant, and only that variant needs to be zero-initialized. So a type that requires explicit initialization can be made zero-initialized by wrapping it with Optional<T>, whose default value is the zero-initialized None value. So even though you end up with coloured data types, they're easily contained & they do not spread virally. I think this offers the best of both worlds. It gives you explicit nullability while still permitting something like `make([]SomeStruct, n)` to return a big block of zeroes. > Languages like Rust were designed from day zero around explicit individual-element based initialization > Ownership is a constant concern and mental overhead when thinking in an individual-element mindset. Whilst ownership is obvious (and usually trivial) in the vast majority (99+%) of cases when you are in the grouped-element mindset. I think there's a sort of convergence here, because one of the tips that's often recommended for dealing with lifetimes issues in Rust (e.g. cyclic data structures) is grouping elements together in a parent structure and referring to them with handles instead of references. Often this is done with integer handles in a simple Vec<T>, but libraries like slotmap exist which make that pattern safer & more ergonomic, if desired. The language features of Rust naturally encourage grouped-element thinking by making individual-element strategies high friction. In fact, I wouldn't be surprised if a reliance on individual-element strategies were part of the reason so many people struggle with Rust when they're first learning the language. Ownership and lifetimes are a source of essential complexity in programming. I don't see any contradiction between managing them with a grouped-element mindset and managing them with language features; in fact, I think the two go hand-in-hand quite nicely. |
Rust by default doesn't really encourage the group-element mindset and people have to work against the language in order to do it. And what usually happens is people work around the borrow-check as a result, through the use of a handle system. And they do this in order to get the lifetime benefits, performance benefits, and also get around the problems of the ownership semantics.
Of course you can do this in Rust, but the point is that the default approach in Rust does not encourage it at all. The default Rust mindset is the individual-element mindset.