rust / intermediate
Snippet
Understanding Rust Closures: Fn, FnMut, and FnOnce
Rust closures are anonymous functions that capture their environment. The three closure traits represent different ownership behaviors: Fn borrows immutably, FnMut borrows mutably, and FnOnce takes ownership. Understanding these traits is crucial for writing higher-order functions and efficient callback patterns.
snippet.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
fn main() {let x = 10;// Fn: borrows values immutablylet print_x = || println!("x = {}", x);print_x();// FnMut: mutably borrows valueslet mut counter = 0;let mut increment = || {counter += 1;println!("Counter: {}", counter);};increment();// FnOnce: consumes values (takes ownership)let data = vec![1, 2, 3];let consume_data = || {println!("Data: {:?}", data);// data is moved here};consume_data();// Higher-order function taking closureslet result = apply_twice(5, |n| n * n);println!("Result: {}", result);}fn apply_twice<F>(value: i32, f: F) -> i32whereF: Fn(i32) -> i32,{f(f(value))}
Breakdown
1
let print_x = || println!("x = {}", x);
A closure that borrows x immutably - implements Fn trait
2
let mut increment = || { counter += 1; ...
A closure that mutably borrows counter - implements FnMut trait
3
let consume_data = || { println!("{:?}", data);
A closure that moves data into itself - implements FnOnce trait
4
where F: Fn(i32) -> i32
Generic bound specifying the closure type that apply_twice accepts