Често срещани типажи, итератори и анонимни функции

12 ноември 2019

Преговор

Често използвани типажи

Често използвани типажи

Често използвани типажи

Често използвани типажи

Често използвани типажи

Често използвани типажи

Списък

Clone

1 2 3 4 5
trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) { ... }
}

Clone

1 2 3 4 5
trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) { ... }
}

Clone

1 2 3 4 5
trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) { ... }
}

Clone

1 2 3 4 5
trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) { ... }
}

Clone

1 2 3 4 5
trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) { ... }
}

Clone

1 2 3 4 5
trait Clone {
    fn clone(&self) -> Self;

    fn clone_from(&mut self, source: &Self) { ... }
}

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Copy

1
trait Copy: Clone { }

Можем да имплементираме Copy само ако:

Copy

1
trait Copy: Clone { }

Можем да имплементираме Copy само ако:

Copy

1
trait Copy: Clone { }

Можем да имплементираме Copy само ако:

Drop

1 2 3
pub trait Drop {
    fn drop(&mut self);
}

Drop

1 2 3
pub trait Drop {
    fn drop(&mut self);
}

Drop

1 2 3
pub trait Drop {
    fn drop(&mut self);
}

Drop

1 2 3
pub trait Drop {
    fn drop(&mut self);
}

Drop

1 2 3
pub trait Drop {
    fn drop(&mut self);
}

Drop

1 2 3
pub trait Drop {
    fn drop(&mut self);
}

Default

1 2 3
trait Default {
    fn default() -> Self;
}

Default

1 2 3
trait Default {
    fn default() -> Self;
}

Default

1 2 3
trait Default {
    fn default() -> Self;
}

Default

1 2 3
trait Default {
    fn default() -> Self;
}

Default

1 2 3
trait Default {
    fn default() -> Self;
}

Hash

Hash

Hash

Hash

Hash

Display & Debug

Ще видим как да накараме println! да работи за наш тип

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct MagicTrick {
    description: String,
    secrets: Vec<String>,
    skills: Vec<String>,
}

let trick = MagicTrick {
    description: String::from("Изчезваща монета"),
    secrets: vec![String::from("Монетата се прибира в ръкава")],
    skills: vec![String::from("Бързи ръце"), String::from("Заблуда")],
};

println!("{}", trick);
println!("===");
println!("{:?}", trick);
Магически трик "Изчезваща монета" === MagicTrick { description: "Изчезваща монета", secrets: ["Монетата се прибира в ръкава"], skills: ["Бързи ръце", "Заблуда"] }
use std::fmt::{self, Display, Formatter};
impl Display for MagicTrick {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Магически трик {:?}", self.description)
}
}
#[derive(Debug)]
struct MagicTrick {
    description: String,
    secrets: Vec,
    skills: Vec,
}

fn main() {
let trick = MagicTrick {
    description: String::from("Изчезваща монета"),
    secrets: vec![String::from("Монетата се прибира в ръкава")],
    skills: vec![String::from("Бързи ръце"), String::from("Заблуда")],
};

println!("{}", trick);
println!("===");
println!("{:?}", trick);
}

Display

Display

Display

Display

Display

1 2 3 4 5 6 7
use std::fmt::{self, Display, Formatter};

impl Display for MagicTrick {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Магически трик {:?}", self.description)
    }
}
#![allow(dead_code)]
struct MagicTrick { description: String }
fn main() {}
use std::fmt::{self, Display, Formatter};

impl Display for MagicTrick {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "Магически трик {:?}", self.description)
    }
}

Display

Нека да разбием примера и да видим какво oзначават новите неща

Макрос write

1
write!(f, "Магически трик {:?}", self.description)

Макрос write

1
write!(f, "Магически трик {:?}", self.description)

Макрос write

1
write!(f, "Магически трик {:?}", self.description)

Display

1 2 3 4 5 6 7 8 9 10 11 12 13
struct MagicTrick {
    description: String,
    secrets: Vec<String>,
    skills: Vec<String>,
}

let trick = MagicTrick {
    description: String::from("Изчезваща монета"),
    secrets: vec![String::from("Монетата се прибира в ръкава")],
    skills: vec![String::from("Бързи ръце"), String::from("Заблуда")],
};

println!("{}", trick);
Магически трик "Изчезваща монета"
#![allow(dead_code)]
use std::fmt::{self, Display, Formatter};
impl Display for MagicTrick {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Магически трик {:?}", self.description)
}
}
struct MagicTrick {
    description: String,
    secrets: Vec,
    skills: Vec,
}

fn main() {
let trick = MagicTrick {
    description: String::from("Изчезваща монета"),
    secrets: vec![String::from("Монетата се прибира в ръкава")],
    skills: vec![String::from("Бързи ръце"), String::from("Заблуда")],
};

println!("{}", trick);
}

Debug

Debug

Debug

Debug

Debug

Може да напишем и собствена имплементация

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
use std::fmt::{self, Debug, Formatter};

impl Debug for MagicTrick {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write! {
            f,
r#"Трик
Описание: {:?}
Тайни: {:?}
Умения: {:?}"#,
            self.description,
            self.secrets,
            self.skills
        }
    }
}
#![allow(dead_code)]
fn main() {}
struct MagicTrick {
description: String,
secrets: Vec,
skills: Vec
}
use std::fmt::{self, Debug, Formatter};

impl Debug for MagicTrick {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write! {
            f,
r#"Трик
Описание: {:?}
Тайни: {:?}
Умения: {:?}"#,
            self.description,
            self.secrets,
            self.skills
        }
    }
}

Display & Debug

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct MagicTrick {
    description: String,
    secrets: Vec<String>,
    skills: Vec<String>,
}

let trick = MagicTrick {
    description: String::from("Изчезваща монета"),
    secrets: vec![String::from("Монетата се прибира в ръкава")],
    skills: vec![String::from("Бързи ръце"), String::from("Заблуда")],
};

println!("{}", trick);
println!("===");
println!("{:?}", trick);
Магически трик "Изчезваща монета" === Трик Описание: "Изчезваща монета" Тайни: ["Монетата се прибира в ръкава"] Умения: ["Бързи ръце", "Заблуда"]
#![allow(dead_code)]
use std::fmt::{self, Display, Debug, Formatter};
impl Display for MagicTrick {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Магически трик {:?}", self.description)
}
}
impl Debug for MagicTrick {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write! { f,
r#"Трик
Описание: {:?}
Тайни: {:?}
Умения: {:?}"#,
self.description, self.secrets, self.skills
}
}
}
struct MagicTrick {
    description: String,
    secrets: Vec,
    skills: Vec,
}

fn main() {
let trick = MagicTrick {
    description: String::from("Изчезваща монета"),
    secrets: vec![String::from("Монетата се прибира в ръкава")],
    skills: vec![String::from("Бързи ръце"), String::from("Заблуда")],
};

println!("{}", trick);
println!("===");
println!("{:?}", trick);
}

Предефиниране на оператори

Операторите се дефинират с trait-ове

Видяхме trait-а Add, с който дефинираме оператора +

1 2 3 4 5
trait Add<RHS = Self> {
    type Output;

    fn add(self, rhs: RHS) -> Self::Output;
}

Предефиниране на оператори

Примери

Предефиниране на оператори

PartialEq

1 2 3 4 5
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
    fn eq(&self, other: &Rhs) -> bool;

    fn ne(&self, other: &Rhs) -> bool { ... }
}

Предефиниране на оператори

PartialEq

1 2 3 4 5
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
    fn eq(&self, other: &Rhs) -> bool;

    fn ne(&self, other: &Rhs) -> bool { ... }
}

Предефиниране на оператори

PartialEq

1 2 3 4 5
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
    fn eq(&self, other: &Rhs) -> bool;

    fn ne(&self, other: &Rhs) -> bool { ... }
}

Предефиниране на оператори

PartialEq

1 2 3 4 5
trait PartialEq<Rhs = Self> where Rhs: ?Sized {
    fn eq(&self, other: &Rhs) -> bool;

    fn ne(&self, other: &Rhs) -> bool { ... }
}

Предефиниране на оператори

Eq

1
trait Eq: PartialEq<Self> { }

Предефиниране на оператори

Eq

1
trait Eq: PartialEq<Self> { }

Предефиниране на оператори

Eq

1
trait Eq: PartialEq<Self> { }

Предефиниране на оператори

PartialOrd

1 2 3 4 5 6 7 8 9 10 11 12 13 14
trait PartialOrd<Rhs = Self>: PartialEq<Rhs> where Rhs: ?Sized {
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering>;

    fn lt(&self, other: &Rhs) -> bool { ... }
    fn le(&self, other: &Rhs) -> bool { ... }
    fn gt(&self, other: &Rhs) -> bool { ... }
    fn ge(&self, other: &Rhs) -> bool { ... }
}

enum Ordering {
    Less,
    Equal,
    Greater,
}

Предефиниране на оператори

PartialOrd

Дефинира операторите < <= > >=

PartialOrd дефинира частична наредба

1 2
assert_eq!(::std::f64::NAN < 0.0, false);
assert_eq!(::std::f64::NAN >= 0.0, false);
fn main() {
assert_eq!(::std::f64::NAN < 0.0, false);
assert_eq!(::std::f64::NAN >= 0.0, false);
}

Предефиниране на оператори

Ord

1 2 3 4 5 6
trait Ord: Eq + PartialOrd<Self> {
    fn cmp(&self, other: &Self) -> Ordering;

    fn max(self, other: Self) -> Self { ... }
    fn min(self, other: Self) -> Self { ... }
}

Дефинира тотална наредба т.е само едно от a < b, a == b, a > b е изпълнено.

Итератори

Итератори

Итераторите си имат типаж, който изглежда така:

1 2 3 4 5 6 7
trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;

    // ... predefined iterator methods ...
}
#![allow(dead_code)]
fn main() {}
trait Iterator {
    type Item;

    fn next(&mut self) -> Option;

    // ... predefined iterator methods ...
}

Итератори

Ето и как може да си имплементиране собствен итератор

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
struct OneTwoThree {
    state: u32,
}

impl OneTwoThree {
    fn new() -> Self {
        Self { state: 0 }
    }
}

impl Iterator for OneTwoThree {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.state < 3 {
            self.state += 1;
            Some(self.state)
        } else {
            None
        }
    }
}
#![allow(dead_code)]
fn main() {}
struct OneTwoThree {
    state: u32,
}

impl OneTwoThree {
    fn new() -> Self {
        Self { state: 0 }
    }
}

impl Iterator for OneTwoThree {
    type Item = u32;

    fn next(&mut self) -> Option {
        if self.state < 3 {
            self.state += 1;
            Some(self.state)
        } else {
            None
        }
    }
}

Итератори

1 2 3 4 5 6 7 8 9 10
fn main() {
    let mut iter = OneTwoThree::new();

    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    // ...
}
Some(1) Some(2) Some(3) None None
#![allow(dead_code)]
struct OneTwoThree {
state: u32,
}
impl Iterator for OneTwoThree {
type Item = u32;
fn next(&mut self) -> Option {
if self.state < 3 { self.state += 1 ; Some(self.state) } else { None }
}
}
impl OneTwoThree {
fn new() -> Self {
Self { state: 0 }
}
}
fn main() {
    let mut iter = OneTwoThree::new();

    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    println!("{:?}", iter.next());
    // ...
}

Итератори

IntoIterator

Указва как може един тип да се конвертира до итератор.

1 2 3 4 5 6
trait IntoIterator
{
    type Item;
    type IntoIter: Iterator<Item=Self::Item>;
    fn into_iter(self) -> Self::IntoIter;
}

Итератори

IntoIterator

1 2 3 4 5 6
let v = vec![1, 2, 3];
let mut iter = v.into_iter();

while let Some(i) = iter.next() {
    println!("{}", i);
}
1 2 3
#![allow(dead_code)]
fn main() {
let v = vec![1, 2, 3];
let mut iter = v.into_iter();

while let Some(i) = iter.next() {
    println!("{}", i);
}
}

Итератори

IntoIterator

Също така получаваме и благото да използваме типа директно във for-in цикли

Тъй като векторите имплементират този типаж, следните два примера са еднакви

1 2 3 4 5
let v = vec![1, 2, 3];

for i in v.into_iter() {
    println!("{}", i);
}

1 2 3

Copy

#![allow(dead_code)]
fn main() {
let v = vec![1, 2, 3];

for i in v.into_iter() {
    println!("{}", i);
}
}

1 2 3 4 5
let v = vec![1, 2, 3];

for i in v {
    println!("{}", i);
}

1 2 3

Copy

#![allow(dead_code)]
fn main() {
let v = vec![1, 2, 3];

for i in v {
    println!("{}", i);
}
}

Итератори

for-in цикъл

Нека отбележим и доста важен факт, че всеки итератор има имплементиран IntoIterator

1 2 3 4 5 6 7 8
impl<I: Iterator> IntoIterator for I {
    type Item = I::Item;
    type IntoIter = I;

    fn into_iter(self) -> I {
        self
    }
}

Итератори

for-in цикъл

1 2 3 4 5
let values = vec![1, 2, 3];

for x in values {
    println!("{}", x);
}
1 2 3
#![allow(dead_code)]
fn main() {
let values = vec![1, 2, 3];

for x in values {
    println!("{}", x);
}
}

Rust генерира следният код зад всеки for-in цикъл:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
let values = vec![1, 2, 3];
{
    let result = match IntoIterator::into_iter(values) {
        mut iter => loop {
            let next;
            match iter.next() {
                Some(val) => next = val,
                None => break,
            };
            let x = next;
            let () = { println!("{}", x); };
        },
    };
    result
}
1 2 3
#![allow(dead_code)]
fn main() {
let values = vec![1, 2, 3];
{
    let result = match IntoIterator::into_iter(values) {
        mut iter => loop {
            let next;
            match iter.next() {
                Some(val) => next = val,
                None => break,
            };
            let x = next;
            let () = { println!("{}", x); };
        },
    };
    result
}
}

Итератори

FromIterator

Обратно на IntoIterator, FromIterator се използва за да укаже как един итератор да се конвертира до тип, най-често структура от данни.

1 2 3
trait FromIterator<A>: Sized {
    fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> Self;
}

Итератори

FromIterator

Обратно на IntoIterator, FromIterator се използва за да укаже как един итератор да се конвертира до тип, най-често структура от данни.

1 2 3
trait FromIterator<A>: Sized {
    fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> Self;
}

Ще видим как това е полезно при итератор адаптeрите.

Итератори

Vec

Има две интересни имплементации на Iterator за Vec, освен стандартната

1 2 3 4
impl<T> IntoIterator for Vec<T>

impl<'a, T> IntoIterator for &'a mut Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>

Итератори

Vec

които позволяват взаимно заменяемия код

1 2 3 4
let v = vec![1, 2, 3];
for i in v.iter() {
    println!("{}", i);
}

1 2 3

Copy

fn main() {
let v = vec![1, 2, 3];
for i in v.iter() {
    println!("{}", i);
}
}

1 2 3 4
let v = vec![1, 2, 3];
for i in &v {
    println!("{}", i);
}

1 2 3

Copy

fn main() {
let v = vec![1, 2, 3];
for i in &v {
    println!("{}", i);
}
}

Итератори

Vec

както и mutable версията

1 2 3 4 5
let mut v = vec![1, 2, 3];
for i in v.iter_mut() {
    *i += 1;
}
println!("{:?}", v);

[2, 3, 4]

Copy

fn main() {
let mut v = vec![1, 2, 3];
for i in v.iter_mut() {
    *i += 1;
}
println!("{:?}", v);
}

1 2 3 4 5
let mut v = vec![1, 2, 3];
for i in &mut v {
    *i += 1;
}
println!("{:?}", v);

[2, 3, 4]

Copy

fn main() {
let mut v = vec![1, 2, 3];
for i in &mut v {
    *i += 1;
}
println!("{:?}", v);
}

Итератори

Адаптери

Итератори

Адаптери

1 2 3 4 5
let v = vec![1, 2, 3];
let iter = v.into_iter().map(|x| x + 1).filter(|&x| x < 4);
for i in iter {
    println!("{}", i);
}
2 3
fn main() {
let v = vec![1, 2, 3];
let iter = v.into_iter().map(|x| x + 1).filter(|&x| x < 4);
for i in iter {
    println!("{}", i);
}
}

Итератори

Адаптери

1 2 3 4 5
let v = vec![1, 2, 3];
let iter = v.into_iter().map(|x| x + 1).filter(|&x| x < 4);
for i in iter {
    println!("{}", i);
}
2 3
fn main() {
let v = vec![1, 2, 3];
let iter = v.into_iter().map(|x| x + 1).filter(|&x| x < 4);
for i in iter {
    println!("{}", i);
}
}

Итератори

Адаптери

1 2 3 4 5
let v = vec![1, 2, 3];
let iter = v.into_iter().map(|x| x + 1).filter(|&x| x < 4);
for i in iter {
    println!("{}", i);
}
2 3
fn main() {
let v = vec![1, 2, 3];
let iter = v.into_iter().map(|x| x + 1).filter(|&x| x < 4);
for i in iter {
    println!("{}", i);
}
}

Итератори

Адаптери

1 2 3 4 5 6 7 8
let v = vec![1, 2, 3];
let v = v
    .into_iter()
    .map(|x| x + 1)
    .filter(|&x| x < 4)
    .collect::<Vec<_>>();

println!("{:?}", v);
[2, 3]
fn main() {
let v = vec![1, 2, 3];
let v = v
    .into_iter()
    .map(|x| x + 1)
    .filter(|&x| x < 4)
    .collect::>();

println!("{:?}", v);
}

Итератори

Адаптери

1 2 3 4 5 6 7 8
let v = vec![1, 2, 3];
let v = v
    .into_iter()
    .map(|x| x + 1)
    .filter(|&x| x < 4)
    .collect::<Vec<_>>();

println!("{:?}", v);
[2, 3]
fn main() {
let v = vec![1, 2, 3];
let v = v
    .into_iter()
    .map(|x| x + 1)
    .filter(|&x| x < 4)
    .collect::>();

println!("{:?}", v);
}

Това е възможно защото collect извиква вътрешно FromIterator::from_iter.

Итератори

Адаптери

Преди да правите някакви странни цикли за трансформация, разгледайте какви адаптери има за Iterator.

Closures

Closures

syntax

1 2 3
|x: u32| -> u32 { x + 1 };
|x|             { x + 1 };
|x|               x + 1  ;

Closure vs fn

Каква е разликата между функция и closure?

Closures могат да използват променливи дефинирани по-горе в scope-a.

1 2 3 4 5
fn main() {
    let other = String::from("foo");               // <-+
                                                   //   |
    Some("bar").map(|s| s.len() + other.len());    // --+
}
fn main() {
    let other = String::from("foo");               // <-+
                                                   //   |
    Some("bar").map(|s| s.len() + other.len());    // --+
}

Вътрешна имплементация

Зад кулисите компилаторът създава една структура и една функция

1 2 3 4 5 6 7 8 9 10 11
/// Структура в която запомняме променливите, които сме прихванали
struct State {
    other: String,
}

impl State {
    /// Функция която съдържа логиката
    fn call(&self, s: &str) -> usize {
        s.len() + self.other.len()
    }
}
#![allow(dead_code)]
fn main() {}
/// Структура в която запомняме променливите, които сме прихванали
struct State {
    other: String,
}

impl State {
    /// Функция която съдържа логиката
    fn call(&self, s: &str) -> usize {
        s.len() + self.other.len()
    }
}

Вътрешна имплементация

1 2 3 4 5 6 7 8 9 10 11 12
fn map_option(opt: Option<&str>, f: State) -> Option<usize> {
    match opt {
        Some(s) => Some(f.call(s)),
        None => None,
    }
}

fn main() {
    let other = String::from("foo");

    map_option(Some("bar"), State { other });
}
#![allow(dead_code)]
struct State {
other: String,
}
impl State {
fn call(&self, s: &str) -> usize {
s.len() + self.other.len()
}
}
fn map_option(opt: Option<&str>, f: State) -> Option {
    match opt {
        Some(s) => Some(f.call(s)),
        None => None,
    }
}

fn main() {
    let other = String::from("foo");

    map_option(Some("bar"), State { other });
}

Move closure

Една подробност - closure-ите не консумират прихванатите променливи

1 2 3 4 5 6 7
let other = String::from("foo");

println!("{:?}", Some("bar").map(|s| s.len() + other.len()));
println!("{:?}", other);       // Ок

println!("{:?}", map_option(Some("bar"), State { other }));
// println!("{:?}", other);    // комп. грешка - use of moved value `other`
Some(6) "foo" Some(6)
#![allow(dead_code)]
struct State {
other: String,
}
impl State {
fn call(&self, s: &str) -> usize {
s.len() + self.other.len()
}
}
fn map_option(opt: Option<&str>, f: State) -> Option {
match opt {
Some(s) => Some(f.call(s)),
None => None,
}
}
fn main() {
let other = String::from("foo");

println!("{:?}", Some("bar").map(|s| s.len() + other.len()));
println!("{:?}", other);       // Ок

println!("{:?}", map_option(Some("bar"), State { other }));
// println!("{:?}", other);    // комп. грешка - use of moved value `other`
}

Move closure

По подразбиране променливите се прихващат по референция

Можем да променим това с ключовата дума move

1 2 3 4 5 6 7
|s| s.len() + other.len();

// генерира

struct State<'a> {
    other: &'a String
}

1 2 3 4 5 6 7
move |s| s.len() + other.len();

// генерира

struct State {
    other: String
}

Fn traits

Fn traits

Синтаксис

Fn traits

FnOnce

1 2 3 4 5
// опростено
trait FnOnce<Args> {
    type Output;
    fn call_once(self, args: Args) -> Self::Output;
}

Fn traits

FnOnce

1 2 3 4 5
// опростено
trait FnOnce<Args> {
    type Output;
    fn call_once(self, args: Args) -> Self::Output;
}

Fn traits

FnOnce

1 2 3 4 5
// опростено
trait FnOnce<Args> {
    type Output;
    fn call_once(self, args: Args) -> Self::Output;
}

Fn traits

FnOnce

1 2 3 4 5
// опростено
trait FnOnce<Args> {
    type Output;
    fn call_once(self, args: Args) -> Self::Output;
}

Fn traits

FnMut

1 2 3 4
// опростено
trait FnMut<Args>: FnOnce<Args> {
    fn call_mut(&mut self, args: Args) -> Self::Output;
}

Fn traits

FnMut

1 2 3 4
// опростено
trait FnMut<Args>: FnOnce<Args> {
    fn call_mut(&mut self, args: Args) -> Self::Output;
}

Fn traits

Fn

1 2 3 4
// опростено
trait Fn<Args>: FnMut<Args> {
    fn call(&self, args: Args) -> Self::Output;
}

Fn traits

Fn

1 2 3 4
// опростено
trait Fn<Args>: FnMut<Args> {
    fn call(&self, args: Args) -> Self::Output;
}

Fn traits

Когато създадем closure, компилатора имплементира всички trait-ове, който може

Fn traits

Когато създадем closure, компилатора имплементира всички trait-ове, който може

Fn traits

Когато създадем closure, компилатора имплементира всички trait-ове, който може

Fn traits

Когато създадем closure, компилатора имплементира всички trait-ове, който може

Fn traits

Когато създадем closure, компилатора имплементира всички trait-ове, който може

Fn traits

Когато създадем closure, компилатора имплементира всички trait-ове, който може

Taking closures

По-популярния начин за взимане на closure е чрез static dispatch

1 2 3 4 5
fn eval_and_increment<F>(f: F) -> usize where F: Fn???() -> usize {
    f() + 1
}

println!("{}", eval_and_increment(|| 1));

Taking closures

Кой Fn trait да сложим за ограничение?

Taking closures

Кой Fn trait да сложим за ограничение?

Taking closures

Кой Fn trait да сложим за ограничение?

Taking closures

Кой Fn trait да сложим за ограничение?

Taking closures

Кой Fn trait да сложим за ограничение?

Taking closures

Кой Fn trait да сложим за ограничение?

Taking closures

1 2 3 4 5
fn eval_and_increment<F>(f: F) -> usize where F: FnOnce() -> usize {
    f() + 1
}

println!("{}", eval_and_increment(|| 1));
2
fn eval_and_increment(f: F) -> usize where F: FnOnce() -> usize {
    f() + 1
}

fn main() {
println!("{}", eval_and_increment(|| 1));
}

Въпроси