Nim's ARC is similar to Rust's memory management, they both do compile time insertion of destructors. Nim's ORC is ARC but with a cycle collector(which as I believe Rust doesnt need since it requires unsafe code to have cylical types). I suggest reading these two blogs for a deeper explanation.
I talked about it on Hacker News the other day and withoutboats (Rust contributor, implemented async await in Rust) said:
withoutboats2 43 days ago [–]
"It is not at all like Rust; it is a garbage collection system based on reference counting, pretty similar to Swift. This is obscured by the documentation for each using similar terminology (like "move semantics" and "ownership") to refer to systems with different characteristics."
It would be great if someone could explain the differences in more details.
In reality Swift, C++, Nim and Rust all work very similarly. At the same time there are big differences in the details.
Rust also uses a garbage collection system based on reference counting ... ;-) Yes, really. It uses 1-bit reference counts under the covers and full reference counts for Rc<T> and Arc<T>,
I might be wrong here, please correct me if so, but:
I think that equivalent code written in Rust and Nim would generally result in similar or even equivalent code that calls destructors and does not increase or decrease reference counts.
Code that would actually modify reference counts in Nim would not compile in Rust as it would violate the borrow checker requirements. Unless you use Rc/Arc in rust, in which case it would do reference counts just like Nim.
If I'm correct in this, it should be possible to add a minor "no refcount" pragma to Nim about a type or piece of code, which will make that type or piece of code behave exactly the way Rust does for those places where it's important (and possibly drop the reference count storage for a type).
If I'm correct in this, ...
Yes, you are.
it should be possible to add a minor "no refcount" pragma to Nim about a type or piece of code, which will make that type or piece of code behave exactly the way Rust does for those places where it's important (and possibly drop the reference count storage for a type).
It's never important though ... the refcount updates are very cheap in Nim, they are not atomic. If you need more speed a "no refcount" pragma is not gonna cut it. Instead you need a different approach based on packing the memory. Also, instead of "no refcount" you can write your own unique_ptr that lacks the refcount. (Or wait until the stdlib caught up and offers unique_ptr.)
On the subject of "no refcount", I have a slightly tangential question...
Strings and seqs in Nim are refs (with refcounts, albeit with copy semantics). As discussed in different threads, including Multi-threaded features needed for Server it is often desirable to store strings and seqs in shared data structures (e.g. shared table). Unfortunately, this doesn't work well for multi-threaded access due to refcounts not being atomic. It requires unnecessary locking or requires making local copies to avoid to avoid corrupting refcounts.
I'm wondering if we could have an equivalent of openarray for seqs and strings? Basically an immutable + no refcount view. This way, the strings and seqs that are shared could be used in all existing code (instead of having to change all proc signatures to allow, e.g., SharedString or SharedSeq)
Would the experimental views allow for something like this?
Unfortunately, this doesn't work well for multi-threaded access due to refcounts not being atomic. It requires unnecessary locking or requires making local copies to avoid to avoid corrupting refcounts.
All it takes is to move the strings/seqs into the shared table. Would be helpful if we had a good shared table implementation somewhere... :-)