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);
}
הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה