Структури, модули, външни пакети

11 октомври 2018

Административни неща

Административни неща

Административни неща

Административни неща

Съдържание

Съдържание

Съдържание

Съдържание

Съдържание

Съдържание

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Типа String

1 2 3 4
let mut s = String::from("hello");
s.push_str(", world");

println!("{}", s);
hello, world

Преговор

Типа &str (string slice)

1 2 3 4 5
let s = String::from("hello, world");
let r1 = &s[..];
let r2 = &r1[1..4];

println!("{}", r2);
ell

Преговор

Tипа Vec

1 2 3 4 5 6
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);

println!("{:?}", v);
[1, 2, 3]

Преговор

.. и макрото vec!

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

println!("{:?}", v);
[1, 2, 3]

Неща, за които не ни стигна времето

Типа &[T]

Неща, за които не ни стигна времето

Типа &[T]

Неща, за които не ни стигна времето

Типа &[T]

Неща, за които не ни стигна времето

Типа &[T]

&[T]

Slice literal

1 2 3
let slice = &[1, 2, 3];

println!("{:?}", slice);
[1, 2, 3]

&[T]

Array slice

1 2 3 4
let arr = [1, 2, 3];
let slice = &arr[..];

println!("{:?}", slice);
[1, 2, 3]

&[T]

Vector slice

1 2 3 4
let v = vec![1, 2, 3];
let slice = &v[..];

println!("{:?}", slice);
[1, 2, 3]

Бонус синтаксис

Бонус синтаксис

Създаване на масиви с еднакви елементи

1 2 3
let zeroed = [0, 0, 0, 0, 0, 0, 0, 0];

println!("{:?}", zeroed);
[0, 0, 0, 0, 0, 0, 0, 0]

Бонус синтаксис

Създаване на масиви с еднакви елементи

1 2 3
let zeroed = [0; 8];

println!("{:?}", zeroed);
[0, 0, 0, 0, 0, 0, 0, 0]

Бонус синтаксис

Създаване на масиви с еднакви елементи

1 2 3
let zeroed = [0; 8];

println!("{:?}", zeroed);
[0, 0, 0, 0, 0, 0, 0, 0]

Синтаксисът е [element; count]

Бонус синтаксис

Създаване на вектори с еднакви елементи

1 2 3
let zeroed = vec![0; 8];

println!("{:?}", zeroed);
[0, 0, 0, 0, 0, 0, 0, 0]

Структури

Структури

Синтаксис

1 2 3 4 5
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}

Структури

Създаване на инстанция

1 2 3 4 5
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

Структури

Достъп до полета

1 2 3 4 5 6 7
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

println!("{}, {}", user.username, user.email);
Иванчо, ivan40@abv.bg

Структури

Достъп до полета

1 2 3 4 5 6 7 8 9
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user_ref = &user;

println!("{}, {}", user_ref.username, user_ref.email);
Иванчо, ivan40@abv.bg

Структури

Достъп до полета

1 2 3 4 5 6 7 8 9
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user_ref = &user;

println!("{}, {}", user_ref.username, user_ref.email);
Иванчо, ivan40@abv.bg

Полетата се доспъпват по същия начин и през референция

Структури

Struct update syntax

1 2 3 4 5 6 7 8 9 10 11 12
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{}, {}", hacker.username, hacker.email);
Иванчо, hackerman@l33t.hax

Методи и асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

1 2 3 4
let user = User::new(
    String::from("Иванчо"),
    String::from("ivan40@abv.bg"),
);

Методи и асоциирани функции

1 2 3 4
let user = User::new(
    String::from("Иванчо"),
    String::from("ivan40@abv.bg"),
);

Методи и асоциирани функции

Конструктури и деструктури

Методи и асоциирани функции

Конструктури и деструктури

Методи и асоциирани функции

Конструктури и деструктури

Методи и асоциирани функции

Конструктури и деструктури

Методи и асоциирани функции

Конструктури и деструктури

Методи и асоциирани функции

Още един пример

1 2 3 4 5 6 7 8 9 10 11
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }

    fn area(&self) -> f64 {
        self.width * self.height
    }
}

Методи и асоциирани функции

Кратък синтаксис за създаване на структури

1 2 3 4 5 6 7
let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width: width,
    height: height,
};

1 2 3 4 5 6 7
let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width,
    height,
};

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

Методи и асоциирани функции

Методи

Методите могат да се използват като най-обикновена функция

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = Rectangle::area(&rect);

println!("{}", area);
6

Методи и асоциирани функции

Методи

Но могат и да се извикват със синтаксиса за методи

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("{}", area);
6

Методи и асоциирани функции

Методи

Но могат и да се извикват със синтаксиса за методи

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("{}", area);
6

Методи и асоциирани функции

Методи

Но могат и да се извикват със синтаксиса за методи

1 2 3 4
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("{}", area);
6

Tuple structs

Именувани кортежи

1 2 3 4 5
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

Tuple structs

Полетата се достъпват с .0, .1, и т.н.

1 2 3 4 5
struct Color(i32, i32, i32);

let black = Color(0, 0, 0);

println!("r: {}, g: {}, b: {}", black.0, black.1, black.2);
r: 0, g: 0, b: 0

Празни структури

1 2 3 4 5
struct Electron {}
struct Proton;

let x = Electron {};
let y = Proton;

Модули

Модули

cargo new communicator --lib

1 2 3 4
communicator
├── Cargo.toml
└── src
    └── lib.rs

Модули

Модули в същия файл

1 2 3 4 5 6 7 8 9 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }
}

mod client {
    fn connect() {
        // ...
    }
}

Модули

Модули в отделни файлове

1 2 3 4
// src/lib.rs

mod network;
mod client;

1 2 3 4 5
// src/network.rs

fn connect() {
    // ...
}

1 2 3 4 5
// src/client.rs

fn connect() {
    // ...
}

Модули

Модули в отделни файлове

1 2 3 4 5 6
communicator
├── Cargo.toml
└── src
    └── client.rs
    └── lib.rs
    └── network.rs

Подмодули

Подмодули в същия файл

1 2 3 4 5 6 7 8 9 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }

    mod client {
        fn connect() {
            // ...
        }
    }
}

Подмодули

Подмодули в отделни файлове

1 2 3
// src/lib.rs

mod network;

1 2 3 4 5 6 7
// src/network/mod.rs

mod client;

fn connect() {
    // ...
}

1 2 3 4 5
// src/network/client.rs

fn connect() {
    // ...
}

Подмодули

Подмодули в отделни файлове

1 2 3 4 5 6 7
communicator
├── Cargo.toml
└── src
    └── lib.rs
    └── network
        └── client.rs
        └── mod.rs

Подмодули

Подмодули в отделни файлове

1 2 3 4 5 6 7
communicator
├── Cargo.toml
└── src
    └── lib.rs
    └── network
        └── client.rs
        └── mod.rs

Компилаторът търси за файловете MOD_NAME.rs или MOD_NAME/mod.rs

Достъп

В модул имаме директен достъп до всичко останало дефинирано в модула

1 2 3 4 5 6 7 8
mod client {
    fn connect() { /* ... */ }

    fn init() {
        // client::connect();
        connect();
    }
}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        ::client::connect();
    }
}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име..

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        ::client::connect();
    }
}
error[E0603]: function `connect` is private
 --> /src/main_32.rs:8:9
  |
8 |         ::client::connect();
  |         ^^^^^^^^^^^^^^^^^

Достъп

.. и освен това то трябва да е публично достъпно (keyword pub)

1 2 3 4 5 6 7 8 9
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    fn init() {
        ::client::connect();
    }
}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use client::connect;

    fn init() {
        connect();
    }
}

Достъп

Ако искаме да импортираме неща от подмодул, може да използваме use self::... за релативен път

1 2 3 4 5 6 7 8 9 10 11 12
mod network {
    mod client {
        pub fn connect() { /* ... */ }
    }

    // еквивалентно на use network::client::connect;
    use self::client::connect;

    fn init() {
        connect();
    }
}

Достъп: public и private

Достъп: public и private

Достъп: public и private

Достъп: public и private

Достъп: public и private

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod user {
    pub struct User {
        username: String,
        email: String,
    }
}

use self::user::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}

Достъп: public и private

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod user {
    pub struct User {
        username: String,
        email: String,
    }
}

use self::user::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
error[E0451]: field `username` of struct `user::User` is private
  --> /src/main_36.rs:14:9
   |
14 |         username: String::from("Иванчо"),
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `username` is private

error[E0451]: field `email` of struct `user::User` is private
  --> /src/main_36.rs:15:9
   |
15 |         email: String::from("ivan40@abv.bg"),
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ field `email` is private

Достъп: public и private

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod user {
    pub struct User {
        pub username: String,
        pub email: String,
    }
}

use self::user::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}

Достъп: public и private

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
mod user {
    pub struct User {
        username: String,
        email: String,
    }

    pub fn new(username: String, email: String) -> User {
        User { username, email }
    }
}

fn main() {
    let user = user::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}

Достъп: public и private

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
mod user {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod init {
        use super::User;

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}

fn main() {
    let user = user::init::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}

Достъп: public и private

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
mod user {
    mod user {
        pub struct User {
            username: String,
            email: String,
        }
    }

    pub mod init {
        use super::user::User;

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}
error[E0451]: field `username` of struct `user::user::User` is private
  --> /src/main_40.rs:15:20
   |
15 |             User { username, email }
   |                    ^^^^^^^^ field `username` is private

error[E0451]: field `email` of struct `user::user::User` is private
  --> /src/main_40.rs:15:30
   |
15 |             User { username, email }
   |                              ^^^^^ field `email` is private

Пакети

Пакети

Ще си направим игра за отгатване на число

1
cargo new number_guessing_game --bin

Пакети

Пакети

Пакети

Пакети

Cargo.toml

1 2 3 4 5 6
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["Nikola Stoyanov <ns.barzakov@gmail.com>"]

[dependencies]

Cargo.toml

1 2 3 4 5 6 7
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["Nikola Stoyanov <ns.barzakov@gmail.com>"]

[dependencies]
rand = "0.5.5"

Използване

1 2 3
extern crate rand;

// ...

Използване

1 2 3
extern crate rand;

// ...

cargo build

Документация

Документация

Имплементация

Live demo

Въпроси