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

See also:

std::iter::Iterator::any

Searching through iterators

Iterator::find is a function which iterates over an iterator and searches for the first value which satisfies some condition. If none of the values satisfy the condition, it returns None. Its signature:

pub trait Iterator {

// The type being iterated over.

type Item;


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

// and modified, but not consumed.

fn find

(&mut self, predicate: P) -> Option where

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

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

// arguments to the closure by reference.

P: FnMut(&Self::Item) -> bool {}

}

fn main() {

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

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

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

let mut iter = vec1.iter();

// `into_iter()` for vecs yields `i32`.

let mut into_iter = vec2.into_iter();

// `iter()` for vecs yields `&i32`, and we want to reference one of its

// items, so we have to destructure `&&i32` to `i32`

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

// `into_iter()` for vecs yields `i32`, and we want to reference one of

// its items, so we have to destructure `&i32` to `i32`

println!("Find 2 in vec2: {:?}", into_iter.find(| &x| x == 2));

let array1 = [1, 2, 3];

let array2 = [4, 5, 6];

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

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

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

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

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Iterator::find gives you a reference to the item. But if you want the index of the item, use Iterator::position.

fn main() {

let vec = vec![1, 9, 3, 3, 13, 2];

let index_of_first_even_number = vec.iter().position(|x| x % 2 == 0);

assert_eq!(index_of_first_even_number, Some(5));

let index_of_first_negative_number = vec.iter().position(|x| x <&0);

assert_eq!(index_of_first_negative_number, None);

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

See also:

std::iter::Iterator::find

std::iter::Iterator::find_map

std::iter::Iterator::position

std::iter::Iterator::rposition

Higher Order Functions

Rust provides Higher Order Functions (HOF). These are functions that take one or more functions and/or produce a more useful function. HOFs and lazy iterators give Rust its functional flavor.

fn is_odd(n: u32) -> bool {

n % 2 == 1

}

fn main() {

println!("Find the sum of all the squared odd numbers under 1000");

let upper = 1000;

// Imperative approach

// Declare accumulator variable

let mut acc = 0;

// Iterate: 0, 1, 2, ... to infinity

for n in 0.. {

// Square the number

let n_squared = n * n;

if n_squared >= upper {

// Break loop if exceeded the upper limit

break;

} else if is_odd(n_squared) {

// Accumulate value, if it's odd

acc += n_squared;

}

}

println!("imperative style: {}", acc);

// Functional approach

let sum_of_squared_odd_numbers: u32 =

(0..).map(|n| n * n)                             // All natural numbers squared

.take_while(|&n_squared| n_squared < upper) // Below upper limit

.filter(|&n_squared| is_odd(n_squared))     // That are odd

.fold(0, |acc, n_squared| acc + n_squared); // Sum them

println!("functional style: {}", sum_of_squared_odd_numbers);

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Option and Iterator implement their fair share of HOFs.

Diverging functions

Diverging functions never return. They are marked using !, which is an empty type.


#![allow(unused)]

fn main() {

fn foo() -> ! {

panic!("This call never returns.");

}

}

As opposed to all the other types, this one cannot be instantiated, because the set of all possible values this type can have is empty. Note that, it is different from the () type, which has exactly one possible value.

For example, this function returns as usual, although there is no information in the return value.

fn some_fn() {

()

}


fn main() {

let a: () = some_fn();

println!("This function returns and you can see this line.")

}

As opposed to this function, which will never return the control back to the caller.

#![feature(never_type)]


fn main() {

let x: ! = panic!("This call never returns.");

println!("You will never see this line!");

}

Although this might seem like an abstract concept, it is in fact very useful and often handy. The main advantage of this type is that it can be cast to any other one and therefore used at places where an exact type is required, for instance in match branches. This allows us to write code like this: