It’s not necessarily better, but the mutating ones are often the core primitives because they can avoid allocations more often. (If you’re used to things like Java/C#, Rust’s
String is more like C#'s
StringBuilder – which is also preferred over repeatedly adding C#
strings together because it can better amortize allocation costs.)
Another reason is that many things work on slices instead of mutable objects. For things like “I want to sort the first 10 elements of this vector”, it’s way easier to
v[..10].sort_unstable() instead of splitting it, sorting one of them, and joining back together – in addition to needing no allocations instead of potentially 4 if all those operations made new copies.
You definitely want to check out iterators for most cases of “do stuff to a collection without modifying the original”, as it can often stream things together nicely and only
.collect() into a collection at the end. For things like sorting, which aren’t offered streaming, consider things like
IterTools::sorted that encapsulates the collect-then-sort-then-return-it steps.