In this lesson, you will learn how to propagate changes across multiple functions by passing a mutable reference from one scope to another.
The Concept of Chaining
Sometimes, you have a piece of data that needs to be modified by several different functions in a specific order. Instead of returning the value back and forth, you can simply pass a mutable reference (&mut T) down a chain of functions. As long as you maintain the chain of borrowing, each function can perform its specific update on the original data.
How it Works
When you pass a mutable reference into a function, that function gains exclusive access to the data. If that function calls another function and passes the reference along, it is essentially "delegating" its right to modify the data to the next function in line.
Consider this example:
fn add_bonus(score: &mut i32) {
*score += 10;
}
fn apply_penalty(score: &mut i32) {
*score -= 5;
// We can chain another call here!
add_bonus(score);
}
fn main() {
let mut my_score = 100;
// We pass the mutable reference to the first function
apply_penalty(&mut my_score);
println!("Final score: {}", my_score); // Prints: 105
}
Why This Matters
In this pattern, main owns the data. It hands a mutable reference to apply_penalty. Because apply_penalty has an exclusive lock on that data, it is allowed to pass that same "right to mutate" to add_bonus.
By chaining, you avoid the need to move ownership of the value in and out of every function. Instead, the data stays exactly where it is in memory, and the "permissions" to modify it move through your program logic like a relay baton. Remember: because of Rust's exclusivity rules, only one function in the chain can technically hold the mutable reference at any single moment, ensuring your data remains safe from conflicting changes.
Key Takeaway: Mutable reference chaining allows you to delegate modification authority across multiple functions without transferring ownership or creating duplicate copies of your data.