I am trying to understand mutability.
When I declare a variable in Rust with
let mut a = String::from("Foo");
I can modify the Object, e.g.:
a.push_str("Bar");
Or assign a new Object, e.g:
a = String::from("Bar");
When I declare a variable without 'mut'
let a = String::from("Foo");
I can neither modify the Object nor assign a new Object.
So I can either choose to:
I wonder if it is possible to declare vaiables so that
I read the chapter about mutability in the book but couln't find any information which could help me further.
First, we need to make an important distinction:
In let mut
, mut
is a property of the binding, i.e. the variable. The variable and everything it contains can be mutated, but only as long as it contains it. We can transfer the content to another variable, and then mutability will be decided by the new one:
let v = String::from("Foo");
// Cannot mutate `v`.
v.clear(); // ERROR
v = String::new(); // ERROR
let mut new_v = v;
new_v.clear(); // OK
new_v = String::new(); // OK
In contrast, mutability of references (&
and &mut
) is a property of the value. Even if we transfer ownership, shared references cannot be mutated (unless they contain interior mutability).
Now, I can answer your questions:
the object is immutable, but the variable is mutable and can be assigned to a different object or
Yes, if we make the variable a shared reference:
let mut v = &String::from("Foo");
v.clear(); // ERROR
let other = String::new();
v = &other; // OK
the object is mutable, but the variable is immutable and cannot be assigned to a different object.
Yes, if an immutable variable contains a mutable reference:
let v = &mut String::from("Foo");
v.clear(); // OK
let mut other = String::new();
v = &mut other; // ERROR
Another way to satisfy (2), as already said, is using interior mutability:
let v = std::cell::RefCell::new(String::from("Foo"));
v.borrow_mut().clear(); // OK
v = String::new(); // ERROR