Здравей, Rust
Въведение
8 октомври 2026
Hello, world!
Защото винаги от там се почва:
fn main() {
println!("Hello, world!");
}
fn main() {
println!("Hello, world!");
}
Компилация
Можем да използваме компилатора на Rust - rustc
Компилация
Можем да използваме компилатора на Rust - rustc
$ rustc hello.rs
$ ./hello
Hello, world!
Компилация
Но, разбира се, има по-лесен начин
Компилация
Но, разбира се, има по-лесен начин
$ cargo new hello
$ cd hello
$ cargo run
Hello, world!
Cargo
Cargo
- Package manager
Cargo
- Package manager
- Task runner
Cargo
- Package manager
- Task runner
- Подобно на
mixв elixir,bundlerв ruby,npm/yarnв node.js
Инсталация
Инсталация
- Rustup (https://rustup.rs/)
Инсталация
- Rustup (https://rustup.rs/)
$ rustup install stable
Инсталация
- Rustup (https://rustup.rs/)
$ rustup install stable$ rustup doc
Инсталация
- Rustup (https://rustup.rs/)
$ rustup install stable$ rustup doc- https://2017.fmi.rust-lang.bg/topics/1
Среда за разработка
Среда за разработка
- текстов редактор, който поддържа LSP (language server protocol)
Среда за разработка
- текстов редактор, който поддържа LSP (language server protocol)
- rust-analyzer
Среда за разработка
- текстов редактор, който поддържа LSP (language server protocol)
- rust-analyzer
rustup component add rust-analyzer
Среда за разработка
- текстов редактор, който поддържа LSP (language server protocol)
- rust-analyzer
rustup component add rust-analyzerrustup component add rustfmt
The Rust Book
Rust playpen
Променливи
Променливи се декларират с let
let NAME = VALUE;
let NAME: TYPE = VALUE;
let x = 5;
let y: i32 = 3;
fn main() {
let x = 5;
let y: i32 = 3;
}
Променливи
Всяка променлива има тип, но можем да не пишем типа, ако е ясен от контекста
let x: i32 = 5;
let y = x; // типа на `y` е `i32`, защото `x` e `i32`
fn main() {
let x: i32 = 5;
let y = x; // типа на `y` е `i32`, защото `x` e `i32`
}
let x = 5; // типа на `x` е `i32`, защото `y` e `i32`
let y: i32 = x;
fn main() {
let x = 5; // типа на `x` е `i32`, защото `y` e `i32`
let y: i32 = x;
}
Променливи
mutability
Променливите са immutable по подразбиране
let x = 5;
x += 1;
Променливи
mutability
Променливите са immutable по подразбиране
let x = 5;
x += 1;
error[E0384]: cannot assign twice to immutable variable `x` --> src/bin/main_36f8492ad48af060e38d104a951ad65bb0005868.rs:5:1 | 4 | let x = 5; | - first assignment to `x` 5 | x += 1; | ^^^^^^ cannot assign twice to immutable variable | help: consider making this binding mutable | 4 | let mut x = 5; | +++ For more information about this error, try `rustc --explain E0384`. error: could not compile `rust` (bin "main_36f8492ad48af060e38d104a951ad65bb0005868") due to 1 previous error
#[allow(unused_assignments)]
fn main() {
let x = 5;
x += 1;
}
Променливи
mutability
За да се направи mutable се използва ключовата дума mut
let mut x = 5;
x += 1;
#[allow(unused_assignments)]
fn main() {
let mut x = 5;
x += 1;
}
Променливи
Засенчване (shadowing)
Можем да декларираме нова променлива със същото име като вече съществуваща.
let x = 10;
let x = x + 10;
let x = x * 3;
println!("{}", x);
60
fn main() {
let x = 10;
let x = x + 10;
let x = x * 3;
println!("{}", x);
}
Променливи
Засенчване (shadowing)
Предишното е еквивалентно на:
let x1 = 10;
let x2 = x1 + 10;
let x3 = x2 * 3;
println!("{}", x3);
60
fn main() {
let x1 = 10;
let x2 = x1 + 10;
let x3 = x2 * 3;
println!("{}", x3);
}
Основни типове
Целочислени типове
i8,i16,i32,i64,i128,isizeu8,u16,u32,u64,u128,usize
Основни типове
Целочислени типове
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 битов ОС
Основни типове
Целочислени типове
i8,i16,i32,i64,i128,isizeu8,u16,u32,u64,u128,usizeiN- цяло (signed) число с размер N битаuN- неотрицателно (unsigned) число с размер N битаisizeиusizeимат размер колкото машинната дума - 32 бита на 32 битов ОС и 64 бита на 64 битов ОС
let x: u32 = 1337;
fn main() {
let x: u32 = 1337;
}
Основни типове
Целочислени типове (литерали)
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 1_000_000
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 1_000_00042_u32
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 1_000_00042_u321_0_0_0
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 1_000_00042_u321_0_0_01_____________________________________________________4
Основни типове
Целочислени типове (литерали)
- Цяло число:
42 - Специфичен тип:
42u32 - Големи числа:
133_587 1_000_00042_u321_0_0_01_____________________________________________________4
let x: u32 = 1337;
let x = 1337_u32;
fn main() {
let x: u32 = 1337;
let x = 1337_u32;
}
Основни типове
Целочислени типове (в различни бройни системи)
- Hex:
0xDEADBEEF - Octal:
0o77 - Binary:
0b1010011010
Основни типове
Числа с плаваща запетая
f32f64- съответно 32 битов и 64 битов float
3.141.3_f64
Основни типове
Числа с плаваща запетая
f32f64- съответно 32 битов и 64 битов float
3.141.3_f64
let x: f64 = 3.14;
fn main() {
let x: f64 = 3.14;
}
Основни типове
Булеви стойности
bool- стойности
trueиfalse
let x: bool = true;
fn main() {
let x: bool = true;
}
Специфики
Няма автоматично конвертиране между различни числови типове
let x: i32 = 1;
let y: u64 = x;
error[E0308]: mismatched types --> src/bin/main_a6086f539401bbf3b7b549495af4885bf92b9c07.rs:4:14 | 4 | let y: u64 = x; | --- ^ expected `u64`, found `i32` | | | expected due to this | help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit | 4 | let y: u64 = x.try_into().unwrap(); | ++++++++++++++++++++ For more information about this error, try `rustc --explain E0308`. error: could not compile `rust` (bin "main_a6086f539401bbf3b7b549495af4885bf92b9c07") due to 1 previous error
fn main() {
let x: i32 = 1;
let y: u64 = x;
}
Специфики
За конвертиране между типове се използва ключовата дума as.
let x: i32 = 1;
let y: u64 = x as u64;
fn main() {
let x: i32 = 1;
let y: u64 = x as u64;
}
Специфики
Аритметични операции не могат да се прилагат върху различни типове
let x = 4_u32 - 1_u8;
error[E0308]: mismatched types --> src/bin/main_b74b848673d4adf9f397294b8a6806527e7fe9af.rs:3:17 | 3 | let x = 4_u32 - 1_u8; | ^^^^ expected `u32`, found `u8` error[E0277]: cannot subtract `u8` from `u32` --> src/bin/main_b74b848673d4adf9f397294b8a6806527e7fe9af.rs:3:15 | 3 | let x = 4_u32 - 1_u8; | ^ no implementation for `u32 - u8` | = help: the trait `Sub<u8>` is not implemented for `u32` help: the following other types implement trait `Sub<Rhs>` --> /home/nikola/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/arith.rs:210:9 | 210 | const impl Sub for $t { | ^^^^^^^^^^^^^^^^^^^^^ `u32` implements `Sub` ... 225 | sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f16 f32 f64 f128 } | ---------------------------------------------------------------------------------- in this macro invocation | ::: /home/nikola/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/internal_macros.rs:22:9 | 22 | const impl $imp<$u> for &$t { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&u32` implements `Sub<u32>` ... 33 | const impl $imp<&$u> for $t { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `u32` implements `Sub<&u32>` ... 44 | const impl $imp<&$u> for &$t { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&u32` implements `Sub` = note: this error originates in the macro `sub_impl` (in Nightly builds, run with -Z macro-backtrace for more info) Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. error: could not compile `rust` (bin "main_b74b848673d4adf9f397294b8a6806527e7fe9af") due to 2 previous errors
fn main() {
let x = 4_u32 - 1_u8;
}
Специфики
Аритметични операции не могат да се прилагат върху различни типове
let y = 1.2_f64 / 0.8_f32;
error[E0308]: mismatched types --> src/bin/main_4b79085d5e1911494b6d393237ddd8eb8f7a9174.rs:3:19 | 3 | let y = 1.2_f64 / 0.8_f32; | ^^^^^^^ expected `f64`, found `f32` error[E0277]: cannot divide `f64` by `f32` --> src/bin/main_4b79085d5e1911494b6d393237ddd8eb8f7a9174.rs:3:17 | 3 | let y = 1.2_f64 / 0.8_f32; | ^ no implementation for `f64 / f32` | = help: the trait `Div<f32>` is not implemented for `f64` help: the following other types implement trait `Div<Rhs>` --> /home/nikola/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/arith.rs:511:9 | 511 | const impl Div for $t { | ^^^^^^^^^^^^^^^^^^^^^ `f64` implements `Div` ... 524 | div_impl_float! { f16 f32 f64 f128 } | ------------------------------------ in this macro invocation | ::: /home/nikola/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/internal_macros.rs:22:9 | 22 | const impl $imp<$u> for &$t { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&f64` implements `Div<f64>` ... 33 | const impl $imp<&$u> for $t { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `f64` implements `Div<&f64>` ... 44 | const impl $imp<&$u> for &$t { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&f64` implements `Div` = note: this error originates in the macro `div_impl_float` (in Nightly builds, run with -Z macro-backtrace for more info) Some errors have detailed explanations: E0277, E0308. For more information about an error, try `rustc --explain E0277`. error: could not compile `rust` (bin "main_4b79085d5e1911494b6d393237ddd8eb8f7a9174") due to 2 previous errors
fn main() {
let y = 1.2_f64 / 0.8_f32;
}
Специфики
Нужно е експлицитно конвертиране
let x = 4_u32 - (1_u8 as u32);
let y = 1.2_f64 / (0.8_f32 as f64);
fn main() {
let x = 4_u32 - (1_u8 as u32);
let y = 1.2_f64 / (0.8_f32 as f64);
}
Специфики
В режим debug, аритметични операции хвърлят грешка при препълванe (integer overflow / underflow)
let x = std::convert::identity(255_u8);
let y = x + 1; // 💥
thread 'main' (17906) panicked at src/bin/main_c276ec2c64e3cebb86c1043b0cf23009e7fe67a6.rs:3:9: attempt to add with overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
fn main() {
let x = std::convert::identity(255_u8);
let y = x + 1; // 💥
}
Специфики
Няма оператори ++ и --
x += 1;
x -= 1;
Основни типове
unit
- тип
() - стойност
()
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
- големина 0 байта, не носи информация
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
- големина 0 байта, не носи информация
let x: () = ();
fn main() {
let x: () = ();
}
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
- големина 0 байта, не носи информация
let x: () = ();
fn main() {
let x: () = ();
}
- подобно на
voidв C, но не съвсем
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
- големина 0 байта, не носи информация
let x: () = ();
fn main() {
let x: () = ();
}
- подобно на
voidв C, но не съвсем - използва се, например, за функции, които не връщат резултат
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
- големина 0 байта, не носи информация
let x: () = ();
fn main() {
let x: () = ();
}
- подобно на
voidв C, но не съвсем - използва се, например, за функции, които не връщат резултат
- но има и други приложения
Основни типове
unit
- тип
() - стойност
() - тип с една единствена стойност
- големина 0 байта, не носи информация
let x: () = ();
fn main() {
let x: () = ();
}
- подобно на
voidв C, но не съвсем - използва се, например, за функции, които не връщат резултат
- но има и други приложения
type HashSet<K> = HashMap<K, ()>;
fn main() {
use std::collections::HashMap;
type HashSet = HashMap;
}
Основни типове
Низове
String&str
Основни типове
Низове
String&str- utf8 низ
- няма терминираща нула
Основни типове
Низове
String- динамичен низ
Основни типове
Низове
String- динамичен низ- динамично алокиран
Основни типове
Низове
String- динамичен низ- динамично алокиран
- mutable
Основни типове
Низове
String- динамичен низ- динамично алокиран
- mutable
- подобно на
std::stringв C++
Основни типове
Низове
String- динамичен низ- динамично алокиран
- mutable
- подобно на
std::stringв C++
let s = String::from("Здравей, Rust");
let s = "Здравей, Rust".to_string();
fn main() {
let s = String::from("Здравей, Rust");
let s = "Здравей, Rust".to_string();
}
Основни типове
Низове
&str- резен от низ
Основни типове
Низове
&str- резен от низ- immutable изглед към низ (или част от низ)
Основни типове
Низове
&str- резен от низ- immutable изглед към низ (или част от низ)
- подобно на
char* + lengthв C++
Основни типове
Низове
&str- резен от низ- immutable изглед към низ (или част от низ)
- подобно на
char* + lengthв C++
&str е типа на низовете литерали
let s: &str = "Здравей, Rust";
let hello: &str = &s[0..14];
println!("{:?}", hello);
fn main() {
let s: &str = "Здравей, Rust";
let hello: &str = &s[0..14];
println!("{:?}", hello);
}
Основни типове
Низове
&str- резен от низ- immutable изглед към низ (или част от низ)
- подобно на
char* + lengthв C++
&str може и да сочи към съдържанието на String
let s: String = String::from("Здравей, Rust");
let all: &str = &s;
let hello: &str = &s[0..14];
println!("{:?}", hello);
fn main() {
let s: String = String::from("Здравей, Rust");
let all: &str = &s;
let hello: &str = &s[0..14];
println!("{:?}", hello);
}
Основни типове
Символи
char
Основни типове
Символи
char- unicode code point
- размер 32 бита
let heart1: char = '❤';
let heart2: char = '\u{2764}';
let heart3: &str = "❤";
println!("{:?}", heart1);
println!("{:?}", heart2);
println!("{:?}", heart3);
'❤' '❤' "❤"
fn main() {
let heart1: char = '❤';
let heart2: char = '\u{2764}';
let heart3: &str = "❤";
println!("{:?}", heart1);
println!("{:?}", heart2);
println!("{:?}", heart3);
}
Основни типове
Масиви
Vec<T>- динамичен масив[T; n]- статичен масив&[T]- "резен" от масив
Основни типове
Масиви
Vec<T>- динамичен масив- mutable
- динамично алокиран
- могат да се добавят или премахват елементи
let mut v = vec![1, 2, 3];
v.push(4);
println!("{:?}", v);
[1, 2, 3, 4]
fn main() {
let mut v = vec![1, 2, 3];
v.push(4);
println!("{:?}", v);
}
Основни типове
Масиви
[T; n]- статичен масив
- фиксиран размер
let arr: [i32; 3] = [1, 2, 3];
let nested: [[i32; 3]; 2] = [
[1, 2, 3],
[4, 5, 6],
];
fn main() {
let arr: [i32; 3] = [1, 2, 3];
let nested: [[i32; 3]; 2] = [
[1, 2, 3],
[4, 5, 6],
];
}
Основни типове
Масиви
&[T]- резен от масив- референция към масив или към част от него
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let slice = &arr[1..3];
let slice: &[i32] = &arr[1..3];
println!("{:?}", slice);
[2, 3]
fn main() {
let arr: [i32; 5] = [1, 2, 3, 4, 5];
let slice = &arr[1..3];
let slice: &[i32] = &arr[1..3];
println!("{:?}", slice);
}
Основни типове
Кортежи (tuples)
(A, B, C, ...)
let tuple: (i32, u32, bool) = (1, 2, false);
let unit: () = ();
println!("{}", tuple.0);
println!("{}", tuple.1);
println!("{}", tuple.2);
1 2 false
fn main() {
let tuple: (i32, u32, bool) = (1, 2, false);
let unit: () = ();
println!("{}", tuple.0);
println!("{}", tuple.1);
println!("{}", tuple.2);
}
Основни типове
Структури
struct MyStruct {
field1: String,
field2: u32,
field3: bool,
}
fn main() {}
struct MyStruct {
field1: String,
field2: u32,
field3: bool,
}
Control flow
Control flow
if-клаузи
Синтаксис на if-клауза
if bool_expression {
// ...
} else if another_bool_expression {
// ...
} else {
// ...
}
if 2 > 1 {
println!("okay");
} else {
println!("wait what");
}
fn main() {
let bool_expression = true;
let another_bool_expression = false;
if bool_expression {
// ...
} else if another_bool_expression {
// ...
} else {
// ...
}
if 2 > 1 {
println!("okay");
} else {
println!("wait what");
}
}
Забележете, че няма скоби около условието и скобите за блок { } са задължителни.
Control flow
match
let text = "foobar";
match text {
"foo" => println!("it's foo"),
"bar" => println!("it's bar"),
_ => println!("it's something else: {}", text),
}
it's something else: foobar
fn main() {
let text = "foobar";
match text {
"foo" => println!("it's foo"),
"bar" => println!("it's bar"),
_ => println!("it's something else: {}", text),
}
}
Control flow
Цикли
for цикъла работи с итератори, за които ще говорим в бъдеща лекция
for var in iterable {
// ...
}
for n in [1, 2, 3] {
println!("N: {}", n);
}
fn main() {
let iterable: &[()] = &[];
for var in iterable {
// ...
}
for n in [1, 2, 3] {
println!("N: {}", n);
}
}
Отново няма скоби след for и скобите за блок { } са задължителни.
Control flow
Цикли
Също така има и while и loop цикли.
while bool_expression {
// ...
}
fn main() {
let bool_expression = false;
while bool_expression {
// ...
}
}
loop e същото като while true, но по-четимо.
loop {
// ...
}
fn main() {
loop {
// ...
}
}
Control flow
Цикли
'outer: for x in [1, 2, 3] {
'inner: for y in [4, 5, 6] {
if some_condition {
break 'outer;
}
// ...
}
}
#![allow(unused_labels)]
fn main() {
let some_condition = false;
'outer: for x in [1, 2, 3] {
'inner: for y in [4, 5, 6] {
if some_condition {
break 'outer;
}
// ...
}
}
}
- могат да се слагат етикети на циклите
- етикетите могат да се подават на
breakиcontinue
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)
Декларация, която указва какво трябва да се направи.
Няма стойност, ами предизвиква някакъв страничен ефект.
let x = 10;
Statements & Expressions
Твърдение (statement)
Декларация, която указва какво трябва да се направи.
Няма стойност, ами предизвиква някакъв страничен ефект.
let x = 10;fn add(a: i32, b: i32) { a + b }
Statements & Expressions
Твърдение (statement)
Декларация, която указва какво трябва да се направи.
Няма стойност, ами предизвиква някакъв страничен ефект.
let x = 10;fn add(a: i32, b: i32) { a + b }struct Foo { field1: i32, field2: i32 }
Statements & Expressions
Много от конструкциите на езика са изрази.
Блоковете са израз - стойността им е стойността на последния израз в блока
fn main() {
let x = {
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
x = 3
fn main() {
let x = {
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
Statements & Expressions
if-else конструкцията е израз
let bigger = if a > b {
a
} else {
b
};
fn main() {
let a = 1; let b = 2;
let bigger = if a > b {
a
} else {
b
};
}
По тази причина няма тернарен оператор
let bigger = if a > b { a } else { b };
fn main() {
let a = 1; let b = 2;
let bigger = if a > b { a } else { b };
}
Statements & Expressions
match е израз
let index = match field {
"foo" => 0,
"bar" => 1,
"baz" => 2,
_ => -1,
};
fn main() {
let field = "foo";
let index = match field {
"foo" => 0,
"bar" => 1,
"baz" => 2,
_ => -1,
};
}
Statements & Expressions
loop е израз
let x = loop {
break 5;
};
fn main() {
let x = loop {
break 5;
};
}
Но for и while не са.
Statements & Expressions
Блокове с етикети
fn main() {
let x = 'label: {
if is_error {
break 'label 0;
}
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
x = 3
fn main() {
let is_error = false;
let x = 'label: {
if is_error {
break 'label 0;
}
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
- етикети могат да се слагат и на блокове
break 'labelпозволява "ранно връщане" от блок със стойност
Statements & Expressions
Блокове с етикети
fn main() {
let x = 'label: {
if is_error {
break 'label 0;
}
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
x = 3
fn main() {
let is_error = false;
let x = 'label: {
if is_error {
break 'label 0;
}
let a = 1;
let b = 2;
a + b
};
println!("x = {}", x);
}
- етикети могат да се слагат и на блокове
break 'labelпозволява "ранно връщане" от блок със стойност- помислете дали не е по-четимо да изведете кода в отделна функция
Функции
fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
Hello, world! Another function.
fn main() {
println!("Hello, world!");
another_function();
}
fn another_function() {
println!("Another function.");
}
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
fn main() {}
#[allow(dead_code)]
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
fn main() {}
#[allow(dead_code)]
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
- Задаването на типове на параметрите и резултата е задължително
Функции
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
fn main() {}
#[allow(dead_code)]
fn add(a: u32, b: u32) -> u32 {
// note no semicolon
a + b
}
- Задаването на типове на параметрите и резултата е задължително
- Върнатата стойност е стойността на последния израз в тялото на функцията
Функции
fn print_a(a: u32) {
println!("{}", a);
}
fn print_b(b: u32) -> () {
println!("{}", b);
}
fn main() {}
#[allow(dead_code)]
fn print_a(a: u32) {
println!("{}", a);
}
#[allow(dead_code)]
fn print_b(b: u32) -> () {
println!("{}", b);
}
- Не е нужно да пишем
-> ()за функции който не връщат резулат
Функции
fn good_a(a: u32, a_is_bad: bool) -> u32 {
if a_is_bad {
return 0;
}
a
}
fn main() {}
#[allow(dead_code)]
fn good_a(a: u32, a_is_bad: bool) -> u32 {
if a_is_bad {
return 0;
}
a
}
- Ако искаме да излезем от функцията преди последния ред, може да използваме
return - Използване на
returnна последния ред от тялото се счита за лоша практика
Анонимни функции (closures)
fn add1(a: u32, b: u32) -> u32 {
a + b
}
fn main() {
let add2 = |a, b| { a + b };
println!("add1: {}\nadd2: {}", add1(1, 2), add2(1, 2));
}
add1: 3 add2: 3
fn add1(a: u32, b: u32) -> u32 {
a + b
}
fn main() {
let add2 = |a, b| { a + b };
println!("add1: {}\nadd2: {}", add1(1, 2), add2(1, 2));
}
Анонимни функции (closures)
Анономните функции могат да прихващат променливи от заобикалящия ги lexical scope.
fn main() {
let x = 5;
let add_x = |a| { a + x };
println!("{}", add_x(10));
}
15
fn main() {
let x = 5;
let add_x = |a| { a + x };
println!("{}", add_x(10));
}
- Ще говорим доста повече за тях по-нататък
Macros
- служат за генериране на код
- различават се от функциите по
!след името
Macros
- служат за генериране на код
- различават се от функциите по
!след името println!print!dbg!
println! macro
let x = 5;
let y = "десет";
println!("x = {} and y = {}", x, y);
x = 5 and y = десет
fn main() {
let x = 5;
let y = "десет";
println!("x = {} and y = {}", x, y);
}
println! macro
let x = 5;
let y = "десет";
println!("x = {} and y = {}", x, y);
x = 5 and y = десет
fn main() {
let x = 5;
let y = "десет";
println!("x = {} and y = {}", x, y);
}
- Принтиране на конзолата
println! macro
let x = 5;
let y = "десет";
println!("x = {} and y = {}", x, y);
x = 5 and y = десет
fn main() {
let x = 5;
let y = "десет";
println!("x = {} and y = {}", x, y);
}
- Принтиране на конзолата
{}placeholders
println! macro
let x = 5;
let y = "десет";
println!("x = {:?} and y = {:?}", x, y);
x = 5 and y = "десет"
fn main() {
let x = 5;
let y = "десет";
println!("x = {:?} and y = {:?}", x, y);
}
- Принтиране на конзолата
{:?}placeholders
println! macro
let x = 255;
let y = 10;
println!("x = {:x} and y = {:04}", x, y);
x = ff and y = 0010
fn main() {
let x = 255;
let y = 10;
println!("x = {:x} and y = {:04}", x, y);
}
{:x}и{:0}placeholders и всевъзможни други (std::fmt)
println! macro
let var_x = 5;
let var_y = "десет";
println!("имам {var_x} и {var_y}"); // e еквивалентно на
println!("имам {} и {}", var_x, var_y);
println!("имам {var_x:?} и {var_y:?}"); // е еквивалентно на
println!("имам {:?} и {:?}", var_x, var_y);
имам 5 и десет имам 5 и десет имам 5 и "десет" имам 5 и "десет"
fn main() {
let var_x = 5;
let var_y = "десет";
println!("имам {var_x} и {var_y}"); // e еквивалентно на
println!("имам {} и {}", var_x, var_y);
println!("имам {var_x:?} и {var_y:?}"); // е еквивалентно на
println!("имам {:?} и {:?}", var_x, var_y);
}
- могат да се пишат имена на променливи директно в
{}placeholder-а, вместо да се подават като отделни аргументи - но не могат да се пишат по-сложни изрази
dbg! macro
let x = 5;
let y = "десет";
dbg!(x);
dbg!(y);
[src/bin/main_72fe3d84fb206495b3ff0c4f73c4dc2f69e38ea2.rs:5:1] x = 5 [src/bin/main_72fe3d84fb206495b3ff0c4f73c4dc2f69e38ea2.rs:6:1] y = "десет"
fn main() {
let x = 5;
let y = "десет";
dbg!(x);
dbg!(y);
}
Административни неща
- Инсталирайте си Rust: https://2017.fmi.rust-lang.bg/topics/1
Административни неща
- Инсталирайте си Rust: https://2017.fmi.rust-lang.bg/topics/1
- Регистрирайте се на сайта: https://fmi.rust-lang.bg/
Административни неща
- Инсталирайте си Rust: https://2017.fmi.rust-lang.bg/topics/1
- Регистрирайте се на сайта: https://fmi.rust-lang.bg/
- Имаме и Discord канал: https://discord.gg/r9Wcazk
Материали
- Ако си търсите книжки: https://bitfieldconsulting.com/posts/best-rust-books