Rust Closures Basics
A closure is a small unnamed function that a program can save in a variable. A closure can use the values around the place where it is written.
A named function stands alone
A named function sees only its inputs. The bonus inside main is out of triple's reach:
fn triple(n: i32) -> i32 {
n * 3
}
fn main() {
let bonus = 10;
println!("triple = {}", triple(4));
println!("bonus waits outside = {}", bonus);
}A closure uses the room around it
A closure written in the same room can use the room's values. It borrows bonus, so bonus stays usable after the call:
fn main() {
let bonus = 10;
let add_bonus = |score: i32| score + bonus;
println!("with bonus = {}", add_bonus(32));
println!("bonus still here = {}", bonus);
}Hand a closure to a method
Many methods ask for a small job in the form of a closure. sort_by_key sorts by whatever its closure hands back:
fn main() {
let mut words = ["banana", "kiwi", "apple"];
words.sort_by_key(|w| w.len());
println!("{:?}", words);
}move hands the values over
The word move gives the closure the room's values to keep. The old name stops working:
fn main() {
let greeting = String::from("hello");
let say = move || println!("{}", greeting);
say();
// println!("{}", greeting); // error: greeting was moved into the closure
}Example
fn main() {
let limit = 10;
let over_limit = |n: i32| n > limit;
let scores = [7, 12, 4, 20];
let mut big = 0;
for s in scores {
if over_limit(s) {
big += 1;
}
}
println!("scores over {} = {}", limit, big);
let mut names = ["cy", "ada", "bo"];
names.sort_by_key(|n| n.len());
println!("by length = {:?}", names);
}Key points
- Unlike a named function, a closure can reach the values in the room where it is written.
- A closure is written with its inputs between two bars, like |x| x + 1.
- The types of a closure's inputs are usually guessed from how the closure is used.
- Use the word move when the closure must own the values it uses.
In this example, over_limit is a closure. It borrows limit from the room around it, so the test n > limit can read the 10. The for loop calls it on each score, and two scores pass. Then sort_by_key receives a second closure. That one hands back each name's length, and the names come out shortest first. Rust Closures, in the Intermediate course, goes deeper from here — how closures capture values, and the traits behind them.
Note
A closure borrows what it uses by default.
The move word turns that borrow into ownership.
Try it Yourself
Edit the code, then press Run.
Running is simulated · Rust Playground
Exercise
A closure written inside main uses a variable from main. What happens to that variable?