In Rust, closures are anonymous functions that can capture their environment. The syntax and functionality of closures are similar to regular functions, but closures can capture the values of external variables. This makes closures well-suited for functional programming paradigms, such as iteration, mapping, and other scenarios requiring lambda functions.
Defining Closures
The definition of a closure typically includes a pair of vertical bars || containing a parameter list, followed by an expression or code block. The complete syntax is as follows:
rustlet closure_name = |param1, param2, ...| -> ReturnType { // Closure body };
If the compiler can infer the return type from the context, you can omit the -> ReturnType part.
Example
Let's examine a concrete example. Suppose we have an array, and we want to compute the sum of all elements greater than a certain threshold. This can be efficiently implemented using a closure:
rustfn main() { let numbers = vec![1, 2, 3, 4, 5]; let threshold = 3; // Define a closure that captures the `threshold` variable from its environment let above_threshold = |num| num > threshold; // Use the closure to filter the array and then compute the sum let sum: i32 = numbers.iter().filter(|&&num| above_threshold(num)).sum(); println!("Sum of numbers above threshold: {}", sum); }
In this example, we define a closure named above_threshold that takes a parameter num and returns a boolean indicating whether num exceeds threshold. We then use this closure as the argument to the .filter() method to select elements above the threshold, and apply .sum() to calculate their total.
Interaction with Environment
Closures can capture variables from their environment in three ways:
- By reference (default): using
&T. - By mutable reference: using
&mut T. - By value: using the
movekeyword to move the variable into the closure.
For instance, if you need to modify an external variable within a closure, you can use the move keyword:
rustfn main() { let mut count = 0; let mut increment = || { count += 1; println!("Count: {}", count); }; increment(); increment(); // Note that `count` cannot be directly accessed anymore, as it has been moved into the closure `increment`. }
Here, the closure increment takes ownership of the variable count, so count is inaccessible outside the closure.
Summary
Closures in Rust are a powerful tool that enables writing compact and flexible code. By capturing and manipulating variables from the environment, closures support diverse programming tasks, ranging from simple array operations to complex functional programming patterns.