Mutating &str
only allows you to set it to other pre-existing strings (with compatible lifetime), or parts of those.
You could for example swap between two strings
let mut s: &str = "Hello world!";
let mut t: &str = "Bye world!";
for _ in 0..10 {
std::mem::swap(&mut s, &mut t);
println!("{s} .. {t}");
}
If there’s more than a handful of strings you want to operate between, you won’t see your line anymore though, because they would be in a data structure. E.g. a lot of &str
s could be in a vector, which would reasonably be mutable if you wanted to do things like sorting it
let mut v: Vec<&str> = …;
v.sort();
which is an indirect way of having something like (a lot of) mutable &str
.
If you only have a single string s
, then all you can mutate it is to substrings of itself. Also, mutable variables in Rust for single transformation steps aren’t all that common. For example if you have
let mut s: &str = " Hello World! \n\n";
then you could do
let mut s: &str = " Hello World! \n\n";
s = s.trim();
println!("{s}");
but this would be more commonly written using shadowing and a new immutable variable of the same bname
let s: &str = " Hello World! \n\n";
let s = s.trim();
println!("{s}");
Where mutable variables are super useful is for loops. But when do you ever have a single (of few) strings, and want to make them shorter and shorter subsequences in a loop? Not so common, so you don’t see it. We can of course make a toy example nonetheless:
fn print_shrinking_initial_substrings(full_string: &str) {
let mut s: &str = full_string;
while !s.is_empty() {
println!("{}", s);
s = &s[..s.char_indices().next_back().unwrap().0];
}
}
print_shrinking_initial_substrings("Hello, 世界!");