|
What "immutable" means in Rust is very different from Java or any FP language for thar matter. In Rust you can take any data structure and mutate it. There are hardly any invariants that you can force, unlike in Java. For example, strings are mutable in Rust. This, coupled with not being a language managed by GC, makes persistent data structures not practical or desirable. Of course, mutability in Rust is very controlled, as variables being mutated can't be observed in an unsafe way. So it matters less if strings are mutable. E.g., you won't be able to mutate a string while it's used as a key in a hashmap. But the fact is that, while Rust provides a high degree of safety, functions in Rust are usually side effecting, which means no referential transparency, no equational reasoning, hard to refactor, etc. In Java, culturally speaking, you don't see much immutability, but when you have immutability, it tends to matter much like in FP languages. And Rust is definitely not one of those languages. |
In Rust on the other hand, even though ref cells are a thing as well, the main approach to mutation is through mutable bindings and mutable references, which preserve const-correctness (inspired by C++), i.e. there is a certain degree of transitivity in the guarantees around immutability. When I see an immutable reference in Rust and pass it to a function (or a method), then, outside of few special cases, I can reasonably expect it to stay unmodified. In ML I can’t, unless the code is written in a very unoptimal way, i.e. with persistent data structures anywhere and everywhere, and still the type system won’t give me any hints about that.