Module 2 • Lesson 10

Mutable References

📚 8 min read 💻 Free Course 🦀 nixus.pro

Mutable References

fn append(s: &mut String, extra: &str) {
    s.push_str(extra);
}

fn main() {
    let mut s = String::from("hello");
    append(&mut s, ", world");
    println!("{}", s); // "hello, world"

    // Aliasing XOR Mutability rule:
    let mut data = String::from("abc");
    {
        let r1 = &data;   // immutable
        let r2 = &data;   // also fine
        println!("{} {}", r1, r2);
        // r1, r2 end here (NLL)
    }
    let r3 = &mut data;   // Now mutable is fine
    r3.push('d');
    println!("{}", r3);
}

// Interior mutability with RefCell:
use std::cell::RefCell;

fn interior_mutability() {
    let x = RefCell::new(vec![1, 2, 3]);
    x.borrow_mut().push(4); // Runtime borrow check
    println!("{:?}", x.borrow()); // [1, 2, 3, 4]
}

Common Mutable Reference Patterns

fn sort_desc(v: &mut Vec) {
    v.sort_by(|a, b| b.cmp(a));
}

fn capitalize(s: &mut String) {
    if let Some(c) = s.get_mut(0..1) {
        c.make_ascii_uppercase();
    }
}

fn double_values(v: &mut Vec) {
    for x in v.iter_mut() {
        *x *= 2;
    }
}

fn main() {
    let mut nums = vec![3, 1, 4, 1, 5, 9, 2, 6];
    sort_desc(&mut nums);
    println!("{:?}", nums);

    double_values(&mut nums);
    println!("{:?}", nums);
}

🎯 Practice

  1. Write fn remove_duplicates(v: &mut Vec<i32>) that removes duplicates in-place
  2. Write fn normalize(v: &mut Vec<f64>) that scales values to [0.0, 1.0]
  3. Use RefCell to create a logger that can be "borrowed mutably" through an immutable reference

🎉 Key Takeaways