Rust на примерах — страница 40 из 65

println!("Итерирование по массиву {:?}", &array);

for i in array.iter() {

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

}

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

impl Trait

Если ваша функция возвращает тип, реализующий MyTrait, вы можете записать возвращаемый тип как -> impl MyTrait. Это может достаточно сильно упростить сигнатуру вашей функции!

use std::iter;

use std::vec::IntoIter;

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

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

fn combine_vecs_explicit_return_type(

v: Vec,

u: Vec,

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

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

}

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

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

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

}

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

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) -> impl Iterator + 'a {

numbers

.iter()

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

.map(|x| x * 2)

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Типаж Clone

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

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

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

#[derive(Debug, Clone, Copy)]

struct Unit;

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

#[derive(Clone, Debug)]

struct Pair(Box, Box);

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;

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

// Ошибка! `pair` потеряла свои ресурсы

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

// ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку

// Скопируем `moved_pair` в `cloned_pair` (включая ресурсы)

let cloned_pair = moved_pair.clone();

// Сбросим оригинальную пару используя std::mem::drop

drop(moved_pair);

// Ошибка! `moved_pair` была сброшена

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

// ЗАДАНИЕ ^ Попробуйте раскомментировать эту строку

// Полученный результат из .clone() все ещё можно использовать!

println!("клон: {:?}", cloned_pair);

}

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