Closure
in Rust is a function which is able to capture vairable from context, which is global to it.
For example:
const x: u8 = 10u8;
const closure: fn(u8) -> u8 = |y: u8| -> u8 x * y;
fn func() -> u8 {
closure(5u8)
}
It is allowed in Rust to not put type annotations in closure definition. This way types will be infered from the context.
let closure = |y| x * y;
By default Rust compiler takes least possible ownership on enclosed variables. To force closure to take ownership on
enclosed scope you can use move
keyword:
fn with_moving_ownership() {
let x = 5u8;
let closure = move || {
println!("{}", x)
}
// here x is not available
}
Passing Closure As A Parameter
But when passing a reference to the closure, definition of it's signature is mandatory. To desribe closure there are exist several traits:
Fn
- this means, that captured values will be reference with&
FnOnce
- closure takes full ownership on the captured valuesFnMut
- closure has mutable reference on the captures values with&mut
But these traits define a maximum restriction possible for access to closed scope. But it does not mean that this borrowing will actually happen. If compiler will see that it can use less restrictive borrowing rule it will use it.
Any regular function, which satisfies to the required function trait may be passed as a parameter instead of closure.
Returning A Closure From Function
It is possible to return closure from function. But it is associated with additional restrictions. Returned closure must
own all it's enclosed variables. To do this, use move
keyword. Also we have to use impl
keyword for returned closure type, e.g:
fn create_sum() -> impl Fn(u8) -> u8 {
let x1 = 5u8;
move |y| y + x1
}
Or return pointer to function:
fn create_sum_box() -> Box<dyn Fn(u8) -> u8> {
let x1 = 5u8;
Box::new(move |y| y * x1)
}