The most fundamental idea of functional programming is function as a value. There are more functional types than ordinary functions.

Closures

Besides ordinary functions, rust also supports anonymous function types called closure. Closures are unique, anonymous function type that cannot be written out. Closures are special that they can capture the environment. They can be thought as an object that has captured values as a field and one single method.

Capture Modes

The compiler prefers to capture a closed-over variable by immutable borrow, followed by unique immutable borrow (see below), by mutable borrow, and finally by move. It will pick the first choice of these that is compatible with how the captured variable is used inside the closure body. The compiler does not take surrounding code into account, such as the lifetimes of involved variables, or of the closure itself.

If the move keyword is used, then all captures are by move or, for Copy types, by copy, regardless of whether a borrow would work. The move keyword is usually used to allow the closure to outlive the captured values, such as if the closure is being returned or used to spawn a new thread.

Unique Immutable Borrow

Captures can occur by a special kind of borrow called a unique immutable borrow, which cannot be used anywhere else in the language and cannot be written out explicitly. It occurs when modifying the referent of a mutable reference. Mutably borrowing immutable variable which binds to a mutable reference of something is impossible (since it’s immutable variable). However it is possible to mutate the referent of the mutable reference. Therefore in this case Rust does not allow other variables to reference the mutable reference.

Function Pointers

Function pointer types, written using the fn keyword, refer to a function whose identity is not necessarily known at compile-time. They can be created via a coercion from both function items(see below) and non-capturing closures.

Example of function pointer type is: fn(i32, i32) -> i32.

Function Items

When referred to, a function item, or the constructor of a tuple-like struct or enum variant, yields a zero-sized value of its function item type. That type explicitly identifies the function - its name, its type arguments, and its early-bound lifetime arguments (but not its late-bound lifetime arguments) - so the value does not need to contain an actual function pointer, and no indirection is needed when the function is called. There is no syntax that directly refers to a function item type, but the compiler will display the type as something like fn(u32) -> i32 {fn_name} in error messages.

Coercion to Function Pointers

Various function item types with same signature are refered by same function pointer type. For example, fn incr(x: u32, delta: u32) -> u32 and fn decr(x: u32, delta: u32) -> u32 are different function item types, but both they can be pointed by fn(u32, u32) -> u32 type.

Function Traits

Every functional types implement at least one Fn traits - Fn, FnMut, FnOnce. It depends on the way a closure captures and handles values from environment.

  • FnOnce applies to functional types that can be called once. All functional types implement at least this trait, because all of them can at least be called. A closure that moves captured values out of its body will only implement FnOnce and none of the other Fn traits, because it can only be called once. Therefore calling this type consumes the function.
  • FnMut applies to functional types that don’t move captured values out of their body, but that might mutate the captured values. These types can be called more than once. Calling this type mutably references the function.
  • Fn applies to functional types that don’t move captured values out of their body and that don’t mutate captured values, as well as functions that capture nothing from their environment. These types can be called more than once without mutating their environment, which is important in cases such as calling a closure multiple times concurrently.

FnMut is a supertrait of Fn, and FnOnce is a supertrait of FnMut.


Back