That’s a fun one. I’ve written a few functions with mutable, non-reference parameters - usually when porting directly from C++ and its ilk. It’s a good way to let the function modify the parameter without side-effects - that is, the changes to the parameter never leave the function.
Say you had a function:
fn do_stuff(mut n: i32) {
while n > 0 {
// Do something with n here!
n -= 1;
}
}
When you call do_stuff
, it modifies n
inside the function - but the original n that is passed in never changes. n
is either a copy or a move depending upon the type - but it is now local to the function, just as if you’d typed let mut n = 5
as the first line of the function. So when you call it:
let mut n = 5;
do_stuff(n);
println!("{}", n);
You still get the output of 5, because n
is copied (i32
copies by default - most primitives do). Whereas if you’d use a mutable reference, you’d get:
fn do_stuff(n: &mut i32) {
while n > 0 {
// Do something with n here!
n -= 1;
}
}
..
let mut n = 5;
do_stuff(&mut n);
println!("{}", n);
You will get the output 0
, because the original n
was modified.
I often think of mutable borrow parameters as “out” parameters (some other languages use that terminology) - because they are effectively returning something, even if they are doing it through a parameter rather than a return statement.
Hope that helps! (Sorry about the edits; I wrote it on my phone the first time, and Rust isn’t well suited to mobile keyboards)