Higher-Order Functions
In this page:
Passing a Closure as a Parameter
A function can accept a closure as a parameter by specifying a trait bound like Fn(i32) -> i32, which describes any callable that takes an i32 and returns an i32.
Example: Passing a Closure as a Parameter
fn apply_twice<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
f(f(x))
}
fn main() {
let result = apply_twice(|n| n + 3, 10);
println!("{}", result);
}
Login to try C/C++/Java/PHP code in the editor
Using map with a Closure
The standard library's .map() method on iterators is a higher-order function: it takes a closure and applies it to every element, producing a new iterator of transformed values.
Example: Using map with a Closure
fn main() {
let numbers = vec![1, 2, 3];
let doubled: Vec<i32> = numbers.iter().map(|n| n * 2).collect();
println!("{:?}", doubled);
}
Login to try C/C++/Java/PHP code in the editor
Returning a Closure
Functions can also return closures, typically boxed behind Box<dyn Fn(...) -> ...> since closures have unique, unnamed types that need to be captured in a trait object to return.
Example: Returning a Closure
fn make_adder(amount: i32) -> Box<dyn Fn(i32) -> i32> {
Box::new(move |x| x + amount)
}
fn main() {
let add_five = make_adder(5);
println!("{}", add_five(10));
}
Login to try C/C++/Java/PHP code in the editor
Passing a Named Function Instead of a Closure
Because plain functions and closures without captures share a compatible shape, you can pass a named function directly wherever a matching closure type is expected.
Example: Passing a Named Function Instead of a Closure
fn triple(x: i32) -> i32 {
x * 3
}
fn apply(f: fn(i32) -> i32, value: i32) -> i32 {
f(value)
}
fn main() {
println!("{}", apply(triple, 4));
}
Login to try C/C++/Java/PHP code in the editor
- Forgetting to specify the closure trait bound (
Fn,FnMut, orFnOnce) when writing a function that accepts a closure parameter. - Assuming closures and function pointers are exactly interchangeable in every generic context, when their trait bounds differ subtly.
- Overcomplicating simple logic with higher-order functions when a plain loop would be clearer for beginners reading the code.
- A function that accepts a closure or another function as a parameter is called a higher-order function.
- The
Fntrait bound describes a closure that can be called repeatedly without consuming captured variables. - Standard library methods like
.map()and.filter()are higher-order functions taking closures. - Function pointers (
fn(i32) -> i32) can also be passed like values, similar to closures.
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: