I know that Rust provides some additional compile-time checks because of its stricter type system, but it doesn't come for free - it's harder to learn and arguably to read
I know that Rust provides some additional compile-time checks because of its stricter type system, but it doesn't come for free - it's harder to learn and arguably to read
Ownership/borrowing clarifies whether function arguments are given only temporarily to view during the call, or whether they're given to the function to keep and use exclusively. This ensures there won't be any surprise action at distance when the data is mutated, because it's always clear who can do that. In large programs, and when using 3rd party libraries, this is incredibly useful. Compare that to that golang, which has types for slices, but the type system has no opinion on whether data can be appended to a slice or not (what happens depends on capacity at runtime), and you can't lend a slice as a temporary read-only view (without hiding it behind an abstraction that isn't a slice type any more).
Thread safety in the type system reliably catches at compile time a class of data race errors that in other languages could be nearly impossible to find and debug, or at very least would require catching at run time under a sanitizer.
Basically, I don't need ownership, if I don't mutate things. It would be nice to have ownership as a concept, in case I do decide to mutate things, but it sucks to have to pay attention to it, when I don't mutate and to carry that around all the time in the code.
Non-owning non mutating borrow that doesn’t require you to clone/copy:
fn foo(v: &SomeValue)
Transfer of ownership, no clone/copy needed, non mutating: fn foo(v: SomeValue)
Transfer of ownership, foo can mutate: fn foo(mut v: SomeValue)
AFAIK rust already supports all the different expressivity you’re asking for. But if you need two things to maintain ownership over a value, then you have to clone by definition, wrapping in Rc/Arc as needed if you want a single version of the underlying value. You may need to do more syntax juggling than with F# (I don’t know the language so I can’t speak to it) but that’s a tradeoff of being a system engineering language and targeting a completely different spot on the perf target. let v = SomeValue { ... }
foo(&v);
foo(&v);
eprintln!("{}", v.xyz);
You have to take a reference. I'm not sure how you'd like to represent "I pass a non-reference value to a function but still retain ownership without copying" - like what if foo stored the value somewhere? Without a clone/copy to give an isolated instance, you've potentially now got two owners - foo and the caller of foo which isn't legal as ownership is strictly unique. If F# lets you do this, it's likely only because it's generating an implicit copy for you (which Rust is will do transparently for you when you declare your type inheriting Copy).But otherwise I'm not clear what ownership semantics you're trying to express - would be helpful if you could give an example.