Здравей, Rust
Въведение
04 октомври 2018
Административни неща
- Сайт на курса (може би временен): https://fmi.rust-lang.bg/
Административни неща
- Сайт на курса (може би временен): https://fmi.rust-lang.bg/
- Лекции: https://fmi.rust-lang.bg/lectures
Административни неща
- Сайт на курса (може би временен): https://fmi.rust-lang.bg/
- Лекции: https://fmi.rust-lang.bg/lectures
- Discord: https://discord.gg/FCTNfbZ
Hello, world!
Защото винаги от там се почва:
fn main() {
println!("Hello, world!");
}
Компилация
Можем да използваме компилатора на Rust - rustc
Компилация
Можем да използваме компилатора на Rust - rustc
$ rustc hello.rs
$ ./hello
Hello, world!
Компилация
Но, разбира се, има по-лесен начин
Компилация
Но, разбира се, има по-лесен начин
$ cargo new hello
$ cargo run
Hello, world!
Cargo
Cargo
- Package manager
Cargo
- Package manager
- Task runner
Cargo
- Package manager
- Task runner
- Подобно на
mixв elixir,bundlerв ruby,npmв node.js
Инсталация
Инсталация
Инсталация
Инсталация
- https://2017.fmi.rust-lang.bg/topics/1
- Rustup (https://rustup.rs/)
$ rustup install stable
Инсталация
- https://2017.fmi.rust-lang.bg/topics/1
- Rustup (https://rustup.rs/)
$ rustup install stable$ rustup doc
The Rust Book
Rust playpen
Променливи
Променливи се декларират с let
let NAME = VALUE;
let NAME: TYPE = VALUE;
Типът може се пропусне, ако е ясен от контекста.
let x = 5;
let y: i32 = 3;
Променливи
shadowing
let x = 10;
let x = x + 10;
let x = x * 3;
// ...
Променливи
shadowing
let x1 = 10;
let x2 = x1 + 10;
let x3 = x2 * 3;
// ...
Променливи
shadowing
let x = 10;
{
let x = x + 10;
{
let x = x * 3;
// ...
}
}
Променливи
mutability
Променливите са immutable по подразбиране
let x = 5;
x += 1;
Променливи
mutability
Променливите са immutable по подразбиране
let x = 5;
x += 1;
error[E0384]: cannot assign twice to immutable variable `x` --> /src/main_5.rs:6:1 | 5 | let x = 5; | - first assignment to `x` 6 | x += 1; | ^^^^^^ cannot assign twice to immutable variable
Променливи
mutability
За да се направи mutable се използва ключовата дума mut
let mut x = 5;
x += 1;
Основни типове
Целочислени типове
Основни типове
Целочислени типове
i8,i16,i32,i64,i128,isizeu8,u16,u32,u64,u128,usize
Основни типове
Целочислени типове
i8,i16,i32,i64,i128,isizeu8,u16,u32,u64,u128,usizeiN- цяло (signed) число с размер N бита
Основни типове
Целочислени типове
i8,i16,i32,i64,i128,isizeu8,u16,u32,u64,u128,usizeiN- цяло (signed) число с размер N битаuN- неотрицателно (unsigned) число с размер N бита
Основни типове
Целочислени типове
i8,i16,i32,i64,i128,isizeu8,u16,u32,u64,u128,usizeiN- цяло (signed) число с размер N битаuN- неотрицателно (unsigned) число с размер N битаisizeиusizeимат размер колкото машинната дума - 32 бита на 32 битов ОС и 64 бита на 64 битов ОС
Основни типове
Целочислени типове (литерали)
Основни типове
Целочислени типове (литерали)
- Цяло число:
42
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 42_u32
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 42_u321_0_0_0
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 42_u321_0_0_01_____________________________________________________4
Основни типове
Целочислени типове (в различни бройни системи)
Основни типове
Целочислени типове (в различни бройни системи)
- Hex:
0xDEADBEEF
Основни типове
Целочислени типове (в различни бройни системи)
- Hex:
0xDEADBEEF - Octal:
0o77
Основни типове
Целочислени типове (в различни бройни системи)
- Hex:
0xDEADBEEF - Octal:
0o77 - Binary:
0b1010011010
Основни типове
Числа с плаваща запетая
Основни типове
Числа с плаваща запетая
f32f64
Основни типове
Числа с плаваща запетая
f32f64- съответно 32 битов и 64 битов float
Основни типове
bool
Основни типове
bool
bool
Основни типове
bool
bool- стойности
trueиfalse
Основни типове
unit
Основни типове
unit
()
Основни типове
unit
()- тип с големина 0 байта (zero sized type)
- тип без стойност (но не в смисъла на
null) - подобно на
voidв C/C++, но по-полезно - използва се при generics
Основни типове
unit
()- тип с големина 0 байта (zero sized type)
- тип без стойност (но не в смисъла на
null) - подобно на
voidв C/C++, но по-полезно - използва се при generics
let x: () = ();
Основни типове
Низове
Основни типове
Низове
str
Основни типове
Низове
str- utf8 низ
- ще му обърнем повече внимание в бъдеща лекция.
Основни типове
Низове
str- utf8 низ
- ще му обърнем повече внимание в бъдеща лекция.
let s: &str = "Rust рулит!!!";
Основни типове
Символи
Основни типове
Символи
char
Основни типове
Символи
char- unicode code point
- различно е от
u8 - ще му обърнем внимание заедно с низовете
Основни типове
Символи
char- unicode code point
- различно е от
u8 - ще му обърнем внимание заедно с низовете
let love: char = '❤';
Основни типове
Масиви
[T; n]
let arr: [i32; 3] = [1, 2, 3];
let nested: [[i32; 3]; 2] = [
[1, 2, 3],
[4, 5, 6],
];
Основни типове
Кортежи (tuples)
(A, B, C, ...)
let tuple: (i32, u32, bool) = (1, 2, false);
let unit: () = ();
Основни типове
Сравнение със C
| Length | Rust | C/C++ | ||
|---|---|---|---|---|
| Signed | Unsigned | Signed | Unsigned | |
| 8-bit | i8 | u8 | char | unsigned char |
| 16-bit | i16 | u16 | short | unsigned short |
| 32-bit | i32 | u32 | int | unsigned int |
| 64-bit | i64 | u64 | long long | unsigned long long |
| word | isize | usize | long | unsigned long / size_t |
| Length | Rust | C/C++ |
|---|---|---|
| 32-bit | f32 | float |
| 64-bit | f64 | double |
| Rust | C/C++ |
|---|---|
| bool | bool |
| () | void |
Специфики
Няма автоматично конвертиране между различни числови типове
let x: i32 = 1;
let y: u64 = x;
error[E0308]: mismatched types --> /src/main_11.rs:5:14 | 5 | let y: u64 = x; | ^ expected u64, found i32
Специфики
Аритметични операции не могат да се прилагат върху различни типове
let x = 4_u32 - 1_u8;
let y = 1.2_f64 / 0.8_f32;
error[E0308]: mismatched types --> /src/main_12.rs:4:17 | 4 | let x = 4_u32 - 1_u8; | ^^^^ expected u32, found u8 error[E0277]: cannot subtract `u8` from `u32` --> /src/main_12.rs:4:15 | 4 | let x = 4_u32 - 1_u8; | ^ no implementation for `u32 - u8` | = help: the trait `std::ops::Sub<u8>` is not implemented for `u32` error[E0308]: mismatched types --> /src/main_12.rs:5:19 | 5 | let y = 1.2_f64 / 0.8_f32; | ^^^^^^^ expected f64, found f32 error[E0277]: cannot divide `f64` by `f32` --> /src/main_12.rs:5:17 | 5 | let y = 1.2_f64 / 0.8_f32; | ^ no implementation for `f64 / f32` | = help: the trait `std::ops::Div<f32>` is not implemented for `f64`
Специфики
За конвертиране между типове се използва ключовата дума as
let one = true as u8;
let two_hundred = -56_i8 as u8;
let three = 3.14 as u32;
Специфики
В режим debug, аритметични операции хвърлят грешка при препълванe (integer overflow / underflow)
let x = 255_u8;
let y = x + 1; // 💥
println!("{}", y);
thread 'main' panicked at 'attempt to add with overflow', /src/main_14.rs:4:9 note: Run with `RUST_BACKTRACE=1` for a backtrace.
Специфики
Няма оператори ++ и --
x += 1;
x -= 1;
Коментари
Едноредов коментар
// So we’re doing something complicated here, long enough that we need
// multiple lines of comments to do it! Whew! Hopefully, this comment will
// explain what’s going on.
Rust поддържа и блокови коментари
/*
So we’re doing something complicated here, long enough that we need
multiple lines of comments to do it! Whew! Hopefully, this comment will
explain what’s going on.
*/
Control flow
if-клаузи
Синтаксис на if-клауза
if bool_expression {
// ...
} else if another_bool_expression {
// ...
} else {
// ...
}
Забележете, че няма скоби около условието и скобите за блок { } са задължителни.
Control flow
Цикли
for цикъла работи с итератори, за които ще говорим в бъдеща лекция
for var in iterator {
// ...
}
Отново няма скоби след for и скобите за блок { } са задължителни.
Control flow
Цикли
Също така има и while и loop цикли.
loop e същото като while true, но по-четимо.
while bool_expression {
// ...
}
loop {
// ...
}
Функции
fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
Hello, world! Another function.
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
- Задаването на типове на параметрите и резултата е задължително (няма type inference)
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
- Задаването на типове на параметрите и резултата е задължително (няма type inference)
- Върнатата стойност е стойността на последния израз в тялото на функцията
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
- Задаването на типове на параметрите и резултата е задължително (няма type inference)
- Върнатата стойност е стойността на последния израз в тялото на функцията
- Ако искаме да излезем от функцията преди последния ред, може да използваме
return
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
- Задаването на типове на параметрите и резултата е задължително (няма type inference)
- Върнатата стойност е стойността на последния израз в тялото на функцията
- Ако искаме да излезем от функцията преди последния ред, може да използваме
return - Използване на
returnна последния ред от тялото се счита за лоша практика
Statements & Expressions
Израз (expression)
Statements & Expressions
Израз (expression)
- операция, която връща резултат
Statements & Expressions
Израз (expression)
- операция, която връща резултат
1
Statements & Expressions
Израз (expression)
- операция, която връща резултат
1(2 + 3) * 4
Statements & Expressions
Израз (expression)
- операция, която връща резултат
1(2 + 3) * 4add(5, 6)
Statements & Expressions
Твърдение (statement)
Statements & Expressions
Твърдение (statement)
- инструкция, която извършва някакво действие и няма резултат
Statements & Expressions
Твърдение (statement)
- инструкция, която извършва някакво действие и няма резултат
let x = 10;
Statements & Expressions
Твърдение (statement)
- инструкция, която извършва някакво действие и няма резултат
let x = 10;return 25;
Statements & Expressions
Твърдение (statement)
- инструкция, която извършва някакво действие и няма резултат
let x = 10;return 25;fn add(a: i32, b: i32) { a + b }
Statements & Expressions
Твърдение (statement)
- инструкция, която извършва някакво действие и няма резултат
let x = 10;return 25;fn add(a: i32, b: i32) { a + b }- ако добавим
;след израз го превръщаме в твърдение
Statements & Expressions
Твърдение (statement)
Пример: можем да присвояваме стойността на израз на променлива с let, но не и стойността на твърдение (защото няма стойност)
let x = (let y = 10);
error: expected expression, found statement (`let`) --> /src/main_21.rs:3:10 | 3 | let x = (let y = 10); | ^^^ expected expression | = note: variable declaration using `let` is a statement
Statements & Expressions
Много от констукциите на езика са изрази.
Блоковете са израз - стойността им е стойността на последния израз в блока
fn main() {
let x = {
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
x = 3
Statements & Expressions
if-else конструкцията е израз
let bigger = if a > b {
a
} else {
b
};
Rust няма тернарен оператор по тази причина
let bigger = if a > b { a } else { b };
Statements & Expressions
loop е израз
let x = loop {
break 5;
};
Macros
Macros
- служат за генериране на код
Macros
- служат за генериране на код
- различават се от функциите по
!след името
Macros
- служат за генериране на код
- различават се от функциите по
!след името println!
Macros
- служат за генериране на код
- различават се от функциите по
!след името println!print!
println! macro
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
x = 5 and y = 10
println! macro
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
x = 5 and y = 10
- Принтиране на конзолата
println! macro
let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
x = 5 and y = 10
- Принтиране на конзолата
{}placeholders