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

Some(self.curr)

}

}

// Returns a Fibonacci sequence generator

fn fibonacci() -> Fibonacci {

Fibonacci { curr: 0, next: 1 }

}

fn main() {

// `0..3` is an `Iterator` that generates: 0, 1, and 2.

let mut sequence = 0..3;

println!("Four consecutive `next` calls on 0..3");

println!("> {:?}", sequence.next());

println!("> {:?}", sequence.next());

println!("> {:?}", sequence.next());

println!("> {:?}", sequence.next());

// `for` works through an `Iterator` until it returns `None`.

// Each `Some` value is unwrapped and bound to a variable (here, `i`).

println!("Iterate through 0..3 using `for`");

for i in 0..3 {

println!("> {}", i);

}

// The `take(n)` method reduces an `Iterator` to its first `n` terms.

println!("The first four terms of the Fibonacci sequence are: ");

for i in fibonacci().take(4) {

println!("> {}", i);

}

// The `skip(n)` method shortens an `Iterator` by dropping its first `n` terms.

println!("The next four terms of the Fibonacci sequence are: ");

for i in fibonacci().skip(4).take(4) {

println!("> {}", i);

}

let array = [1u32, 3, 3, 7];

// The `iter` method produces an `Iterator` over an array/slice.

println!("Iterate the following array {:?}", &array);

for i in array.iter() {

println!("> {}", i);

}

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

impl Trait

If your function returns a type that implements MyTrait, you can write its return type as -> impl MyTrait. This can help simplify your type signatures quite a lot!

use std::iter;

use std::vec::IntoIter;

// This function combines two `Vec` and returns an iterator over it.

// Look how complicated its return type is!

fn combine_vecs_explicit_return_type(

v: Vec,

u: Vec,

) -> iter::Cycle, IntoIter>> {

v.into_iter().chain(u.into_iter()).cycle()

}

// This is the exact same function, but its return type uses `impl Trait`.

// Look how much simpler it is!

fn combine_vecs(

v: Vec,

u: Vec,

) -> impl Iterator {

v.into_iter().chain(u.into_iter()).cycle()

}

fn main() {

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

let v2 = vec![4, 5];

let mut v3 = combine_vecs(v1, v2);

assert_eq!(Some(1), v3.next());

assert_eq!(Some(2), v3.next());

assert_eq!(Some(3), v3.next());

assert_eq!(Some(4), v3.next());

assert_eq!(Some(5), v3.next());

println!("all done");

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

More importantly, some Rust types can't be written out. For example, every closure has its own unnamed concrete type. Before impl Trait syntax, you had to allocate on the heap in order to return a closure. But now you can do it all statically, like this:

// Returns a function that adds `y` to its input

fn make_adder_function(y: i32) -> impl Fn(i32) -> i32 {

let closure = move |x: i32| { x + y };

closure

}

fn main() {

let plus_one = make_adder_function(1);

assert_eq!(plus_one(2), 3);

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

You can also use impl Trait to return an iterator that uses map or filter closures! This makes using map and filter easier. Because closure types don't have names, you can't write out an explicit return type if your function returns iterators with closures. But with impl Trait you can do this easily:

fn double_positives<'a>(numbers: &'a Vec) -> impl Iterator + 'a {

numbers

.iter()

.filter(|x| x >&&0)

.map(|x| x * 2)

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Clone

When dealing with resources, the default behavior is to transfer them during assignments or function calls. However, sometimes we need to make a copy of the resource as well.

The Clone trait helps us do exactly this. Most commonly, we can use the .clone() method defined by the Clone trait.

// A unit struct without resources

#[derive(Debug, Clone, Copy)]

struct Unit;

// A tuple struct with resources that implements the `Clone` trait

#[derive(Clone, Debug)]

struct Pair(Box, Box);

fn main() {

// Instantiate `Unit`

let unit = Unit;