| > Rust's compiler prevents you from moving data into a method which then nulls it out Just for clarity, we have this in Nim too, eg: type
Foo = ref object
Bar = object
val: Foo not nil
let
f = Bar() # Error, 'val' must be set
proc foobar(f: Foo not nil): Foo not nil =
return nil # Error, can't return nil
foobar(nil) # Error, can't pass nil
> At best this dangling pointer will look at garbage and cause a crash or undefined behavior. At worst, it will look at other, actively-used memory and cause a security vulnerability.In C/C++, yes, but this isn't so applicable to Nim where we have GCed references and 'not nil' constraints. > If you use iterators in Rust, you never need to worry about out of bounds errors Well I was not talking about iterating through a list, but rather maintaining arbitrary indexes to a mutable list. Eg, a Sprite which contains a index to a Texture array. In that scenario it's just as easy to miscalculate and crash your program via a bounds-checking error as it is to crash by nil-deref. > To offer a counter-viewpoint, I find that Option<> (and Result<>) are very easy to reason about.. It's good that Rust works for you, truly. And like I said in another post, I agree Rust's design here may be better for some domains. However, Nim's design still feels more elegant and straight-forward to me. Luckily, we both get a powerful language that suits us, regardless of which one we prefer :) |
Edit:
> Well I was not talking about iterating through a list, but rather maintaining arbitrary indexes to a mutable list. Eg, a Sprite which contains a index to a Texture array. In that scenario it's just as easy to miscalculate and crash your program via a bounds-checking error as it is to crash by nil-deref.
The solution here is to just use a reference instead of an arbitrary index. If you hand out references you can lean on the compiler to enforce memory safety -- the compiler won't let you access data that is no longer alive, won't let you accidentally share across thread boundaries if you don't explicitly want that, etc. And if that was a shared mutable list, it's doubly important to let the compiler help you reason about it, since shared, mutable state is the main source of data races.
This is one of those cases where leveraging the compiler allows you to write better, safer code.