First thing first, since you want set_value
to change the value of a field, it needs to take &mut self
:
impl Characters {
fn set_value(&mut self, value : String) {
for record in self.records {
record.name = value;
}
}
}
This still has several errors, the first of which is:
error[E0507]: cannot move out of `self.records` which is behind a mutable reference
--> src/lib.rs:12:23
|
12 | for record in self.records {
| ^^^^^^^^^^^^
| |
| `self.records` moved due to this implicit call to `.into_iter()`
| move occurs because `self.records` has type `Vec<Character>`, which does not implement the `Copy` trait
|
note: this function takes ownership of the receiver `self`, which moves `self.records`
help: consider iterating over a slice of the `Vec<Character>`'s content to avoid moving into the `for` loop
|
12 | for record in &self.records {
| +
Following the compiler suggestion, we get:
impl Characters {
fn set_value(&mut self, value : String) {
for record in &self.records {
record.name = value;
}
}
}
giving this error:
error[E0594]: cannot assign to `record.name`, which is behind a `&` reference
--> src/lib.rs:13:13
|
12 | for record in &self.records {
| ------------- this iterator yields `&` references
13 | record.name = value;
| ^^^^^^^^^^^ `record` is a `&` reference, so the data it refers to cannot be written
Here the compiler doesn't give a straight solution, but it suggests that the issue is that record
is not mutable. Unfortunately simply using for mut record
doesn't change anything. The solution is actually the same as the first change we made: since we want to modify self.records
, we need to borrow it mutably: for record in &mut self.records
.
While we're here, let's look at the second error:
error[E0382]: use of moved value: `value`
--> src/lib.rs:13:27
|
11 | fn set_value(&mut self, value : String) {
| ----- move occurs because `value` has type `String`, which does not implement the `Copy` trait
12 | for record in &self.records {
13 | record.name = value;
| ^^^^^ value moved here, in previous iteration of loop
This makes sense: once we've moved value
in the first record
, we don't have it anymore so we can't put it in the others. We can ask the compiler for more explanations on the error with rustc --explain E0382
and we get the solution in the third example:
Sometimes we don't want a reference, but a duplicate. All types marked Clone
can be duplicated by calling .clone()
.
If we clone value
, we get:
impl Characters {
fn set_value(&mut self, value : String) {
for record in &mut self.records {
record.name = value.clone();
}
}
}
And now this function compiles. There remains only one error in another part of the code:
error[E0596]: cannot borrow `chars` as mutable, as it is not declared as mutable
--> src/lib.rs:30:5
|
25 | let chars = Characters {
| ----- help: consider changing this to be mutable: `mut chars`
...
30 | chars.set_value("Halfling".to_string());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
Following the compiler suggestion, we write let mut chars
and we get the working solution:
#[derive(Debug)]
struct Character{
name: String,
}
struct Characters {
records : Vec<Character>
}
impl Characters {
fn set_value(&mut self, value : String) {
for record in &mut self.records {
record.name = value.clone();
}
}
}
fn test() {
let hobbits = vec![
Character{name:String::from("Sam")},
Character{name:String::from("Merry")},
Character{name:String::from("Pepper")},
];
let mut chars = Characters {
records : hobbits
};
// Set all names to "Halfling
chars.set_value("Halfling".to_string());
}
Playground