1

After a lot of struggle getting used to borrowing, references, ownership etc. and trying to follow the compiler's suggestions how to fix certain issues, I ended up with the following pair of functions in my first bit of Rust code.

fn adjust_culture(mut cooperating_families: Vec<&mut Family>) {
    for f in cooperating_families.iter_mut() {
        mutate_culture(f);
    }
    let family: Option<&&mut Family> = cooperating_families.choose(&mut rand::thread_rng());
    match family {
        None => {},
        Some(f) => {
            let target: Culture = f.culture;
            for f2 in cooperating_families {
                f2.culture = target;
            }
        }
    }
}

fn mutate_culture(family: &mut Family) {
    if family.seasons_till_next_mutation > 0 {
        family.seasons_till_next_mutation -= 1;
    }
    if family.seasons_till_next_mutation == 0 {
        let i: u8 = rand::thread_rng().gen_range(0, culture_dimensionality);
        family.culture ^= 1 << i;
    }
}

The second one makes sense to me, and preventing it from gaining additional borrowing decoration was a major point getting me to this solution. But adjust_culture confuses me: Why did the compiler suggest to add the mut before cooperating_families in the function's parameter definition?

I thought I would just have to pass a mutable binding to access the fields of the individual families, but with another function

fn extract_resources(patch: Patch, group: Vec<&mut Family>, total_labor_here: usize) -> KCal {
    let labor: u8 = group.iter().map(|f| {f.effective_size as u8}).sum();
    let resources_extracted = resources_from_patch(
        patch, labor as usize, total_labor_here - labor as usize,
        false);
    for family in group {
        family.stored_resources +=
            resources_extracted * family.effective_size as f32 / labor as f32
    }
    return resources_extracted
}

Rust told me that group does not need to be mutable, and now I'm quite confused.

Which bit of adjust_culture has a chance to change the value of cooperating_families instead of just the objects inside it? How do I avoid that from happening – my mental idea of the semantics says is should not happen?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Anaphory
  • 6,045
  • 4
  • 37
  • 68
  • I assume it is just an artefact of language design history that the `mut` comes before the parameter name, not as first element of the type? Because the fact that the Vec must me mutable, even though I touch only its elements, not the pointers it contains, makes some sense. – Anaphory Apr 27 '20 at 10:42
  • 4
    I don't know if I'd call it an *artifact* because that suggests it was by accident. Making mutability the property of a binding and not of a type is an intentional choice in Rust. – trent Apr 27 '20 at 10:55
  • See also: https://stackoverflow.com/q/50124680/1233251 Consuming a value does not require the respective variable to be `mut`. – E_net4 Apr 27 '20 at 12:01
  • Actually, that bit makes sense to me. I'm confused which step in `adjust_culture` Rust thinks changes the value of `cooperating_families`. – Anaphory Apr 27 '20 at 12:22
  • 1
    @Anaphory It's the call to `iter_mut` (which takes a mutable reference). If you merely want to iterate over the values inside (which are mutable references), you could use `into_iter` ( which would consume the vector so you wouldn't be able to use it later) or `iter` (which would iterate over immutable references to the mutable references - not very useful). – SCappella Apr 27 '20 at 13:13
  • 1
    *I'm confused which step* — the compiler error message points directly to the line that requires a variable to be mutable. If you had provided a [MRE] we could demonstrate the error on the playground for you. Otherwise, [this attempted reproduction example](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ce37707335b4e941b91ad8577ce514e2) shows "cannot borrow as mutable" and points to `cooperating_families` when [`iter_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.iter_mut) is called. – Shepmaster Apr 27 '20 at 13:30

0 Answers0