4 ms·
If I understand correctly, that post describes a proposal to add "owned refs" to Nim, not an actual language feature, and that proposal was abandoned / postpone
by geofft 5y ago
If I understand correctly, that post describes a proposal to add "owned refs" to Nim, not an actual language feature, and that proposal was abandoned / postponed in favor of the refcounting approach I linked to: see https://github.com/nim-lang/RFCs/issues/144 https://github.com/nim-lang/RFCs/issues/144 and https://github.com/nim-lang/RFCs/issues/177 https://github.com/nim-lang/RFCs/issues/177 .
But shared/immutable vs. unique/mutable references aren't the same thing, they're something more interesting. Rust has three types of ways you might be able to get at a variable: you could own the variable, you could have a shared/immutable reference to it, or you could have a unique/mutable reference to it. The Nim proposal only distinguishes the ownership case (responsible from freeing the data when it's done - basically RAII or __attribute__((cleanup)) or autorelease) from the unowned case.
Having shared/immutable references gives you a neat feature for achieving correctness, not just memory safety (and I strongly disagree that the idea of "memory safety" in that post really counts, incidentally, because by that definition Heartbleed wasn't a memory-safety bug, but for the sake of argument let's say it does). The compiler prevents you from having more than one mutable reference at a time. It also prevents you from writing data you own while someone holds a reference to it, or even reading data while someone holds a mutable reference. So if you're writing code where you pass a reference to some other routine, and that function ends up holding onto it for future use, you won't be able to modify it. That prevents logical bugs where code doesn't realize that data has changed or conversely doesn't realize that a change hasn't taken effect.
Again, this is not solely about memory safety. This is about easily writing correct code, of which memory safety is one aspect.
You can think of this as basically type-level reader/writer locks. At any given time you can have multiple readers and no writer, or exactly one writer. While runtime memory safety is one thing that reader/writer locks can do (e.g., preventing you from calling realloc() while other people still have a pointer that they intend to read), they're used for a lot more than that.
Furthermore, Rust's approach requires no runtime overhead and preserves correct behavior. Nim's approach requires refcounting, and the post argues that refcounting could be disabled in a release build if you're confident your code is correct.
- jlokier 5y agoThe current direction in Nim is towards borrowing and borrow checking, move semantics with type annotations, and using refcounting where needed. Similar to Rust really, which also uses refcounting where needed. Nim had the concept of borrowing from very early on. It's not a bolt-on, it's part of the design philosophy. But it's had consistency issues. The move semantics in newer Nim improve on it. I would say one of the major things Rust offers over Nim at the moment is the implementation quality of the Rust compiler, standard library and type systems is generally of higher quality and more consistent. Things are thought-through more completely in Rust's design, and tested more against real world problems. The multi-threading in Rust is also of much higher quality. It's just buggy in Nim. Nim however has a much cleaner syntax, and the quality issues could change if the community really wanted that (I don't think it does). They both have slow compile times for large programs.