Closures
| |x| closures | |
| Capture by ref or move | |
| Fn FnMut FnOnce | |
| Sort with closures |
|x| closures
A closure is an anonymous function written inline with vertical bars around its parameters. Types are often omitted because the compiler infers them from use. Double stores its small doubling logic in a variable and calls it like a function.
fn main() {
let double = |x: i32| x * 2;
println!("{}", double(4));
}
The bars replace the fn keyword and the parameter list in one stroke. Bodies with one expression need no braces and no return. Longer bodies add braces exactly like normal functions.
Capture by ref or move
Unlike functions, closures borrow values from the scope around them. Label reads tag without taking ownership, so tag stays usable afterwards. Adding the move keyword instead hands ownership to the closure, which threads require.
fn main() {
let tag = String::from("user");
let label = |id: u32| format!("{}-{}", tag, id);
println!("{}", label(7));
}
Borrowed captures keep the closure tied to its home scope. Moved captures cut that tie so the closure travels alone. The compiler picks borrows by default and move only on request.
Fn FnMut FnOnce
Every closure implements one of three traits that describe how it treats captures. Fn borrows, FnMut mutates through a mutable borrow, and FnOnce consumes. Call twice demands FnMut, since calling the same closure twice rules out consuming it.
fn call_twice<F>(mut f: F)
where
F: FnMut(),
{
f();
f();
}
The parameter must be marked mutable because FnMut calls need one. Plain readers accept Fn, and one shot consumers accept FnOnce. Generic code states exactly how much power it needs and nothing more.
Sort with closures
Sorting with custom order is the everyday closure showcase. Sort by compares pairs with a closure and arranges the vector to match. Length comparison below lines the shortest name up first.
fn main() {
let mut names = vec!["grace", "ada", "linus"];
names.sort_by(|a, b| a.len().cmp(&b.len()));
println!("{:?}", names);
}
The comparator returns an Ordering that tells sort by which side comes first. Equal lengths keep their original relative order. Swap the two sides to flip between ascending and descending order.
Next: Iterators
Article author: Arthur Isaev