Anonymous functions are known as closures in Rust. We can store them in a variable or a function takes them as a parameter. They behave like a function, but they possess the property of capturing values from the environment in which we define them.
Let’s look at the syntax of closures below:
let variable_name = |list of parameters| -> return_type {"body of the closure"};
let
: This is used to declare any variable in rust.
variable_name
: This is the name of the variable we assign the closure to.
list of parameters
: This is the list of parameters we pass to the closure, which is enclosed in between | |
.
return_type
: This contains the return type of values we want to return.
{}
: This contains the body of the closure.
Property | Closure | Function |
Syntax | Parameters passed between | Parameters passed between |
Body | Enclosed between | Mandatory to enclose between |
Return types | Not mandatory | Mandatory |
Data types | Not mandatory | Mandatory |
Environment capturing | Yes | No |
We can call closures in the same way as functions, as shown below:
fn main(){let message = " Welcome to educative ";let print_message = || { println!("Message is : {}", message); };print_message();}
The program uses a closure to print a message. It also demonstrates the environment capturing property of closure.
string.
print_message
with no input parameters. The body of the closure contains a print statement that prints the value of the variable message
defined out of this closure. This is the environment capturing property of closures.All closures implement the fnOnce
trait. With the help of this property, we make sure that we call a closure only once.
A closure can implement a few other call traits depending on how it captures its environment.
fnmut
, which means we can call them using a mutable reference. This is applicable where the closure has to borrow a variable.fn
.move
keyword in closuresWhenever a closure uses a variable from its capturing environment, it captures either by reference or by mutable reference.
The move
keyword helps capture the closure’s environment by value. It gives them the ownership of the variable to the closure.
Let’s look at the code below:
fn main() {let prime_numbers = vec![2, 3, 5,7];let closure_variable = move |vec| vec == prime_numbers;println!("Cannot use prime_numbers here : {:?}", prime_numbers);let new_vector = vec![2, 3, 5,7];assert!(closure_variable(new_vector));}
The above code throws an error:
closure_variable
takes the ownership of the variable prime_numbers
using a move keyword.println!
function borrows the prime_numbers
variable to print, but the compiler throws an error, as the closure now owns the variable, and the move
keyword moves it in the closure.