Understanding Closures in Rust.
--
Summary
- Closures are a combination of a function pointer (
fn
) and a context. - A closure with no context is just a function pointer.
- A closure which has an immutable context belongs to
Fn
. - A closure which has a mutable context belongs to
FnMut
. - A closure that owns its context belongs to
FnOnce
.
Understanding the different types of closures in Rust.
Unlike some other languages, Rust is explicit about our use of the self
parameter. We have to specify self
to be the first parameter of a function signature when we are implementing a struct:
struct MyStruct {
text: &'static str,
number: u32,
}impl MyStruct {
fn new (text: &'static str, number: u32) -> MyStruct {
MyStruct {
text: text,
number: number,
}
} // We have to specify that 'self' is an argument.
fn get_number (&self) -> u32 {
self.number
}
// We can specify different kinds of ownership and mutability of self.
fn inc_number (&mut self) {
self.number += 1;
}
// There are three different types of 'self'
fn destructor (self) {
println!("Destructing {}", self.text);
}
}
As a result, the following two styles are identical:
obj.get_number();
MyStruct::get_number(&obj);
This is in contrast to other languages where self
(or this
) is often implied. Simply associating a function with an object or structure in these languages can imply that the first argument is self
. Demonstrated above, we have four options for self
: an immutable reference, a mutable reference, an owned value, or to not use self
as an argument at all.
As a result, self
implies some sort of context for the execution of the function. it is explicit in Rust, but often implicit elsewhere.
Also in this post we will use the following functions:
fn is_fn <A, R>(_x: fn(A) -> R) {}
fn is_Fn <A, R, F: Fn(A) -> R> (_x: &F) {}
fn is_FnMut <A, R, F: FnMut(A) -> R> (_x: &F) {}
fn is_FnOnce <A, R, F: FnOnce(A) -> R> (_x: &F) {}