Выбрать главу

use std::iter;

use std::vec::IntoIter;

// Эта функция объединяет два `Vec<i32>` и возвращает итератор.

// Посмотрите какой получается сложный тип возвращаемого значения!

fn combine_vecs_explicit_return_type(

v: Vec<i32>,

u: Vec<i32>,

) -> iter::Cycle<iter::Chain<IntoIter<i32>, IntoIter<i32>>> {

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

}

// Это та же самая функция, но в возвращаемом типе использует нотацию `impl Trait`.

// Посмотрите как он упростился!

fn combine_vecs(

v: Vec<i32>,

u: Vec<i32>,

) -> impl Iterator<Item=i32> {

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!("готово");

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Что более важно, некоторые типы в Rust не могут быть записаны. Например, каждое замыкание имеет свой собственный безымянный тип. До появления синтаксиса impl Trait, чтобы вернуть замыкание, вы должны были аллоцировать её в куче. Но теперь вы можете сделать это всё статически, например так:

// Вернём функцию, которая добавляет `y` ко входному значению

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

Вы также можете использовать impl Trait для возврата итератора, который использует замыкания map или filter! Это упрощает использование map и filter. Из-за того, что замыкание не имеет имени, вы не можете явно записать возвращаемый тип для функции, возвращающей итератор с замыканием. Но с impl Trait вы можете сделать это:

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

numbers

.iter()

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

.map(|x| x * 2)

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

При работе с ресурсами, стандартным поведением является передача их (ресурсов) в ходе выполнения или вызов функции. Однако, иногда нам нужно также объявить копию ресурса.

Типаж Clone помогает нам сделать именно это. Чаще всего, мы можем использовать метод .clone() объявленный типажом Clone.

// Единичная структура без ресурсов

#[derive(Debug, Clone, Copy)]

struct Unit;

// Кортежная структура с ресурсами, которая реализует типаж `Clone`

#[derive(Clone, Debug)]

struct Pair(Box<i32>, Box<i32>);

fn main() {

// Объявим экземпляр `Unit`

let unit = Unit;

// Скопируем `Unit`, который не имеет ресурсов для перемещения

let copied_unit = unit;

// Оба `Unit` могут быть использованы независимо

println!("оригинал: {:?}", unit);

println!("копия: {:?}", copied_unit);

// Объявим экземпляр `Pair`

let pair = Pair(Box::new(1), Box::new(2));

println!("оригинал: {:?}", pair);

// Скопируем `pair` в `moved_pair`, перенаправляя ресурсы

let moved_pair = pair;