In this lesson, you will learn how to control whether a closure borrows data from its surrounding scope or takes full ownership of it.
The Problem of Escaping Closures
In Rust, a closure is a function that can "capture" variables from the environment where it was defined. By default, Rust is smart: it tries to borrow those variables (using &) to be as efficient as possible. However, if you want to pass a closure to a new thread or store it in a struct, the compiler might complain. This happens because the variables the closure is "borrowing" might be destroyed while the closure is still alive.
Forcing Ownership with move
To solve this, we use the move keyword. When you prefix a closure with move, you are telling the compiler: "Don't just borrow these variables; take full ownership of them."
Consider this example where we move a String into a closure:
fn main() {
let name = String::from("Rustacean");
// The 'move' keyword forces the closure to take ownership of 'name'
let greeter = move || {
println!("Hello, {}!", name);
};
greeter();
// name is no longer available here; the closure owns it!
}
Why does this matter?
Without the move keyword, the closure would try to borrow name by reference. If we tried to send that closure to another thread, the compiler would stop us because the original name could go out of scope while the thread is still running, leading to a dangling pointer. By using move, we transfer the data into the closure's own memory storage, making it self-contained and safe to use anywhere.
When deciding which to use, ask yourself: Does this closure need to outlive the scope where the variables were created? If the answer is yes, you almost certainly need the move keyword to ensure the closure carries its own data with it.
Key Takeaway: Use the move keyword to force a closure to take ownership of its captured variables, which is essential when a closure needs to live longer than the scope that created it.