After pondering, my single favorite capability of rust is this:
fn modify(val: &mut u8) {
// ...
}
No other language appears to have this seemingly trivial capability; their canonical alternatives are all, IMO, clumsier. In light of the article, is this due to Rust's memory model, or an unrelated language insight?
Because it's not merely mutable, it's exclusive. You get a static guarantee that, for as long as you can use this reference, this is the only reference in the entire program that can mutate this memory.
This is automatically thread-safe, without any locks. It's guaranteed that there can't be any side effects that could affect this memory, no matter what code you call. You don't need any defensive coding copying the memory just in case. It optimizes well, because it's certain that it won't overlap with any other region.
C++ doesn't have that kind of strong no-alias guarantee. Even memory behind const pointers can be mutated by something else at distance. The closest equivalent is C's restrict pointers, but they're more coarse-grained, and aren't checked by the compiler.
Most low-level languages support this, references in C++, pointers in C, ref keyword in C# and Dlang, and so on. It's mostly higher-level languages that do not support such things because it's in the VM semantics that dictate how objects are passed (i.e. in Lua tables are passed by reference, non-table values are passed by copy).
Great point. I, was mistaken; the languages I've used are of the higher-level variety that don't have this feature (And C, which doesn't really have this feature; I don't think that pointers are nearly as nice).
I challenge you to write the function signature I posted in Python, Javascript, or Kotlin; I'm confident you will not be able to, and the alternatives will be more provincial and unergonomic.
Hint: Python and Javascript will use the type passed to determine mutability. Kotlin will let you pass a mutableStateFlow etc that can be used for, e.g., top-level data structure, but not an arbitrary variable. (e.g. a data structure field, or free variable).
The most popular languages, outside of C and C++, cannot pass pointers. And, raw pointers are not ideal; they lose type safety, memory safety etc.
There are always canonical patterns for a given language to write a function like I did. I find them to be universally more complicated and less explicit/versatile than what I posted; they require code to permeate beyond the function signature.
You're correct re the class wrapper (HN nesting limit). Can you see why that solution is complicated, and not versatile? (hint: This limitation will cause ripples of complication throughout your data structures)
I explicitly excluded primitive types in my previous comment.
I have never seem a codebase where this was an issue. The most important concept in programming is defining your data structures. Professional programs almost never operate on primitive data structures, but always on larger structures, like classes or structs.
This is why this is only a problem for you. I don't want to be insulting, but you need to brush up on your data structures. The need to pass a modifiable data structure almost never arises, the idiom in your OP is extremely uncommon and would likely not pass any code review.
It is not a me problem, which is why Rust has fixed this. You are arguing that functions which mutate parameters generally are not useful, which isn't true. You have implied that I have a lack of knowledge of data structures, my code wouldn't pass code review. Reflect: You are proposing it is preferable to have a simple function accept a whole data structure when it may only act on one or more of its fields, and may be used in other places. That is a semantic misdirection, and provincialization.
You have missed the point: Functions should not need to be provincial to a specific data structure. Nor should data structures include field wrappers to subvert a language's sloppy mutation semantics.
The point is that with mutable references, you can modify only the part of the struct you need to, using a general function. You can use this same function to modify a different part of the structure, or a different structure, or a free variable.
Your inference that preferring mutable references to wrapper structs implies insufficient knowledge of data structures is puzzling and incorrect.