Introduction
Higher-order functions are functions that accept other functions or closures as parameters, or return them as results. In Rust, this pattern is central to the Iterator trait, which powers a rich set of chainable adapters for processing sequences of data. Iterators are lazy, meaning adapter chains build up a plan of work but perform no computation until a consuming method is called.
Cricket analogy: A higher-order function is like a team selector that takes a strategy closure as input; Rust's Iterator trait lets you chain filter and map over a season's scores lazily, computing nothing until you call .sum() for total runs.
Syntax
fn apply<F: Fn(i32) -> i32>(f: F, value: i32) -> i32 {
f(value)
}
let result: Vec<i32> = (1..=5)
.map(|x| x * 2)
.filter(|x| x % 3 != 0)
.collect();Explanation
A function like apply above takes a closure as a parameter using a trait bound such as F: Fn(i32) -> i32, letting callers pass in any matching closure or function. The Iterator trait requires only a single method, next(), which returns Some(item) or None when exhausted; every other adapter (map, filter, fold, and dozens more) is built on top of next(). Because iterators are lazy, calling .map() or .filter() alone does nothing — the chain only executes when a consuming method such as .collect(), .sum(), or a for loop pulls values through it. This laziness combined with compiler optimizations lets iterator chains compile down to the same machine code as manually written loops, which is why Rust calls iterators a zero-cost abstraction.
Cricket analogy: An apply(closure) function with bound F: Fn(i32) -> i32 lets a coach pass any run-adjustment formula; the Iterator's next() yields Some(score) or None per over, and calling .sum() on a lazy filter/map chain is what finally totals the runs, compiling as fast as a hand-written loop over the scorecard.
Example
fn apply_twice<F: Fn(i32) -> i32>(f: F, value: i32) -> i32 {
f(f(value))
}
fn main() {
let doubled = apply_twice(|x| x * 2, 5);
println!("doubled twice = {}", doubled);
let numbers = vec![1, 2, 3, 4, 5, 6];
let sum_of_even_squares: i32 = numbers
.iter()
.filter(|&&n| n % 2 == 0)
.map(|&n| n * n)
.fold(0, |acc, n| acc + n);
println!("sum of even squares = {}", sum_of_even_squares);
}Output
doubled twice = 20
sum of even squares = 56Key Takeaways
- Higher-order functions take closures/functions as parameters or return them.
- The Iterator trait requires only next(), which yields Some(item) or None.
- map, filter, fold, and collect are common lazy adapters built on next().
- Iterators do no work until a consuming method like collect() or sum() is called.
- Iterator chains are a zero-cost abstraction, compiling to loop-equivalent performance.
Practice what you learned
1. What single method must a type implement to satisfy the Iterator trait?
2. Given `let it = (1..5).map(|x| x * 2);` with no further code, what happens?
3. Which method would you use to reduce an iterator to a single accumulated value using a custom combining function?
4. What does 'zero-cost abstraction' mean in the context of Rust iterators?
5. Which trait bound would a function use to accept any closure taking an i32 and returning an i32?
Was this page helpful?
You May Also Like
Closures in Rust
Understand Rust closures, their capture modes, and the Fn, FnMut, and FnOnce traits that govern how they use captured variables.
Functions in Rust
Learn how to declare, call, and return values from functions using Rust's fn syntax and expression-based return rules.
Vectors in Rust
A Vec<T> is a growable, heap-allocated list that lets you store a variable number of values of the same type.
Generics in Rust
Generics let you write functions, structs, and enums that work over many types while remaining zero-cost at runtime.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics