Closures

Contents
|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

Related articles
Rust
Rust course: zero to hero in 50 lessons
What is Rust and where it runs
Install Rust
cargo new
Your first program
Variables
Numbers
Strings
Booleans
Tuples
Arrays
Vectors
Slices
if and else
match
Loops
Ownership
Borrowing
Lifetimes
Functions
Structs
Enums in Rust
Advanced match in Rust
Option combinators in Rust
Result and the question mark in Rust
Advanced strings in Rust
Vec methods in Rust
HashMaps in Rust
Modules in Rust
Crates and workspaces in Rust
Testing in Rust
Error handling
Traits
Generics
Trait bounds
Closures
Iterators
Smart pointers
Threads
Mutex and Arc
Files
CLI arguments
Environment variables
Diagnostics
Time
Parsing strings
TCP networking
Capstone: wordfreq CLI
Capstone: tiny HTTP server
Modern Rust tour
Hero roadmap: the whole course on one page
Install Rust on Windows 11
Install Rust on Ubuntu
Install Rust on Rocky Linux
Install Rust on macOS
Install Rust on FreeBSD
Rust in Docker

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: