Rust by Example — страница 20 из 66

Since this new type is of unknown type, any usage in a function will require generics. However, an unbounded type parameter would still be ambiguous and not be allowed. Thus, bounding by one of the traits: Fn, FnMut, or FnOnce (which it implements) is sufficient to specify its type.

// `F` must implement `Fn` for a closure which takes no

// inputs and returns nothing - exactly what is required

// for `print`.

fn apply(f: F) where

F: Fn() {

f();

}

fn main() {

let x = 7;

// Capture `x` into an anonymous type and implement

// `Fn` for it. Store it in `print`.

let print = || println!("{}", x);

apply(print);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

A thorough analysis, Fn, FnMut, and FnOnce

Input functions

Since closures may be used as arguments, you might wonder if the same can be said about functions. And indeed they can! If you declare a function that takes a closure as parameter, then any function that satisfies the trait bound of that closure can be passed as a parameter.

// Define a function which takes a generic `F` argument

// bounded by `Fn`, and calls it

fn call_me(f: F) {

f();

}

// Define a wrapper function satisfying the `Fn` bound

fn function() {

println!("I'm a function!");

}

fn main() {

// Define a closure satisfying the `Fn` bound

let closure = || println!("I'm a closure!");

call_me(closure);

call_me(function);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

As an additional note, the Fn, FnMut, and FnOnce traits dictate how a closure captures variables from the enclosing scope.

See also:

Fn, FnMut, and FnOnce

As output parameters

Closures as input parameters are possible, so returning closures as output parameters should also be possible. However, anonymous closure types are, by definition, unknown, so we have to use impl Trait to return them.

The valid traits for returning a closure are:

   • Fn

   • FnMut

   • FnOnce

Beyond this, the move keyword must be used, which signals that all captures occur by value. This is required because any captures by reference would be dropped as soon as the function exited, leaving invalid references in the closure.

fn create_fn() -> impl Fn() {

let text = "Fn".to_owned();

move || println!("This is a: {}", text)

}

fn create_fnmut() -> impl FnMut() {

let text = "FnMut".to_owned();

move || println!("This is a: {}", text)

}

fn create_fnonce() -> impl FnOnce() {

let text = "FnOnce".to_owned();

move || println!("This is a: {}", text)

}

fn main() {

let fn_plain = create_fn();

let mut fn_mut = create_fnmut();

let fn_once = create_fnonce();

fn_plain();

fn_mut();

fn_once();

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

Fn, FnMut, Generics and impl Trait.

Examples instd

This section contains a few examples of using closures from the std library.

Iterator::any

Iterator::any is a function which when passed an iterator, will return true if any element satisfies the predicate. Otherwise false. Its signature:

pub trait Iterator {

// The type being iterated over.

type Item;


// `any` takes `&mut self` meaning the caller may be borrowed

// and modified, but not consumed.

fn any(&mut self, f: F) -> bool where

// `FnMut` meaning any captured variable may at most be

// modified, not consumed. `Self::Item` states it takes

// arguments to the closure by value.

F: FnMut(Self::Item) -> bool {}

}

fn main() {

let vec1 = vec![1, 2, 3];

let vec2 = vec![4, 5, 6];

// `iter()` for vecs yields `&i32`. Destructure to `i32`.

println!("2 in vec1: {}", vec1.iter()     .any(|&x| x == 2));

// `into_iter()` for vecs yields `i32`. No destructuring required.

println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2));

let array1 = [1, 2, 3];

let array2 = [4, 5, 6];

// `iter()` for arrays yields `&i32`.

println!("2 in array1: {}", array1.iter()     .any(|&x| x == 2));

// `into_iter()` for arrays unusually yields `&i32`.

println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2));

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX