Earlier quoted context omitted.
It's not a question of support, it's a question of defaults. Rust code exercises a single-ownership discipline by default, and you must opt-in to dynamic multi-ownership (via refcounting or otherwise). In languages that have pervasive dynamic multi-ownership by default (via GC, etc.), enforced single-ownership is instead opt-in, which means that you cannot expect code in the wild to use it. In Rust, you can expect co…
True, defaults matter. In many cases, however, using a language that defaults to a GC for memory safety is often preferable or easier. The argument is often about when ownership and borrowing is truly necessary. Rust has its uses, but arguably not all the time and with everything, because of its defaults.
Rust Memory Management: Ownership vs. Reference Counting
31–40 of 54 posts
Re: Rust Memory Management: Ownership vs. Reference Counting
#32Earlier quoted context omitted.
The point of Rust, without counting `unsafe`, is to eliminate memory errors at compile-time. But the point of Rust, when including `unsafe`, is not to entirely eliminate memory errors at compile-time, but to make it feasible to cordon off the unsafe parts into realistically-auditable sections with documented safety invariants. At this it has been dramatically successful, almost beyond anyone's wildest hopes. I have w…
> without counting `unsafe`, Well, if you exclude all the bad code people have wrote, c is a safe language... See the point I'm making here? If coders couldn't be trusted multiple times in the past, and we had to invent language level features to correct them, but they still continued to make either the same, or a new, mistakes.... Why is rust any different? I guarantee you we will be complaining about unsafe rust in…
Nobody is doing this. Please read my comment again.
Re: Rust Memory Management: Ownership vs. Reference Counting
#33I've not really used Rust, and I can certainly appreciate the goal of the language. However this code bothers me, and I can't really articulate why. struct Node { value: i32, children: Vec >>>, parent: Option >>>, // Weak breaks parent→child cycle } I understand its all boxes inside boxes inside boxes, but as an outsider it looks confusing mixing data type semantics with memory managment semantics.
there ought to be a crate that handles "Vechttps://crates.io/crates/orx-concurrent-vec ? haven't tried it yet)
Re: Rust Memory Management: Ownership vs. Reference Counting
#34I've not really used Rust, and I can certainly appreciate the goal of the language. However this code bothers me, and I can't really articulate why. struct Node { value: i32, children: Vec >>>, parent: Option >>>, // Weak breaks parent→child cycle } I understand its all boxes inside boxes inside boxes, but as an outsider it looks confusing mixing data type semantics with memory managment semantics.
Internally shared ownership is a huge anti-pattern and rarely achieves what you’re actually trying to do. Graphs like these are much better represented by splitting the topology from the node data, and using indices or keys to form edges instead of (smart) pointers.
You can use pointers, but then the correct choice is actually raw pointers and `unsafe`, with a safe whole-graph-level API for traversal and access. This is what Rust’s own collection types do internally.
Re: Rust Memory Management: Ownership vs. Reference Counting
#35Rust is becoming less special in this area. Languages such as Dlang, Vlang, and Julia have added optional ownership and borrowing. As these offerings are optional, many can see this as greater programmer freedom to decide what to use for their projects, with languages that are easier to use or read.
In various forms, affine types, linear types, dependent types, effects, formal proofs.
The list is already rather long, D, Chapel, Swift, Linear Haskell, Ox, OCaml, Koka, Ada/SPARK, Mojo,...
Re: Rust Memory Management: Ownership vs. Reference Counting
#36I've not really used Rust, and I can certainly appreciate the goal of the language. However this code bothers me, and I can't really articulate why. struct Node { value: i32, children: Vec >>>, parent: Option >>>, // Weak breaks parent→child cycle } I understand its all boxes inside boxes inside boxes, but as an outsider it looks confusing mixing data type semantics with memory managment semantics.
I wouldn't like to work with it, but I wouldn't be too surprised if I encountered a List>>>. A list, containing optionally-present weak references to a holder object (which you might need if you intend to update such an object from a lambda, as those can only take effectively final variables from their parent scope).
I think there's value to the Rust implementation. In many other languages, these wrappers are either non-optional or hidden away with syntax, but they're still present. The Rust approach puts the developer in charge of how data should be exchanged (copied/borrowed/on stack/in heap/etc.). You can write extremely efficient programs that stack very few of those types, with many restrictions on how they ca be passed around to methods, or you can make your life easier at the cost of some performance and clutter.
For clarity, you could do something like this:
type RVec = Vec>;
type RNode = RefCell;
struct Node {
value: i32,
children: RVec,
parent: Option>
}
That would allow for some much-needed brevity, but it would also fill your code with custom types that others will need to learn about.Re: Rust Memory Management: Ownership vs. Reference Counting
#37Earlier quoted context omitted.
It's not a question of support, it's a question of defaults. Rust code exercises a single-ownership discipline by default, and you must opt-in to dynamic multi-ownership (via refcounting or otherwise). In languages that have pervasive dynamic multi-ownership by default (via GC, etc.), enforced single-ownership is instead opt-in, which means that you cannot expect code in the wild to use it. In Rust, you can expect co…
True, defaults matter. In many cases, however, using a language that defaults to a GC for memory safety is often preferable or easier. The argument is often about when ownership and borrowing is truly necessary. Rust has its uses, but arguably not all the time and with everything, because of its defaults.
It opens up entirely new avenues for statically error-free programming, letting you model things like “if the caller has an instance of this type, I can guarantee that this other larger proposition is true”. Namely without also having to handle the case where the user smuggled another instance from another call site.
This is really, really useful.
Re: Rust Memory Management: Ownership vs. Reference Counting
#38Earlier quoted context omitted.
The point of Rust, without counting `unsafe`, is to eliminate memory errors at compile-time. But the point of Rust, when including `unsafe`, is not to entirely eliminate memory errors at compile-time, but to make it feasible to cordon off the unsafe parts into realistically-auditable sections with documented safety invariants. At this it has been dramatically successful, almost beyond anyone's wildest hopes. I have w…
> without counting `unsafe`, Well, if you exclude all the bad code people have wrote, c is a safe language... See the point I'm making here? If coders couldn't be trusted multiple times in the past, and we had to invent language level features to correct them, but they still continued to make either the same, or a new, mistakes.... Why is rust any different? I guarantee you we will be complaining about unsafe rust in…
Re: Rust Memory Management: Ownership vs. Reference Counting
#39Solid intro. One pattern worth adding: when you're reaching for Rc > for graph-like or self-referential data, an index-based arena (Vec with usize "pointers") is often a third path that keeps you in plain-ownership land — at the cost of pointer identity and some bookkeeping. petgraph, slotmap, and most ECS libraries formalize this. Doesn't replace Arc for genuinely cross-thread shared lifetimes, but it eliminates a l…
Re: Rust Memory Management: Ownership vs. Reference Counting
#40> Every heap allocation has exactly one owner...
This goes one step further, in that every value including on the stack has a single owner. That's why you can't pass the same `let a = [0; 10];` by value multiple times, even though that's an array on the stack.
> Zero overhead — no extra indirection
I think this is slightly misleading for borrowing, since a reference (`&`) is fundamentally a pointer that the compiler ensures upholds some special properties. So borrows come with a pointer deref when used, similarly to a `Box` or `Rc`, etc. I think the intention is to point out the heap allocations when using smart pointers which are definitely more expensive than `&`, but that doesn't really come across.
Only other call-out is that I'm not sure what the various colours indicate throughout. They look really pretty, but I'm not sure when something becomes teal vs yellow vs orange vs purple.