2019-09-01 07:55:27 +00:00
|
|
|
|
---
|
|
|
|
|
contributors:
|
|
|
|
|
- ["P1start", "http://p1start.github.io/"]
|
|
|
|
|
translators:
|
|
|
|
|
- ["Volodymyr Korniichuk", "https://github.com/ezhikus"]
|
|
|
|
|
filename: learnrust-uk.rs
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
Rust - це мова програмування, що розрабляється спільнотою Mozilla Research
|
|
|
|
|
Rust поєднує в собі низькорівневий контроль швидкодії з високорівневими
|
|
|
|
|
інструментами забезпечення гарантій цілісності та безпеки.
|
|
|
|
|
|
|
|
|
|
Rust досягає своїх цілей без автоматичного збирання сміття і не вимагає
|
|
|
|
|
наявності певного середовища виконання, що робить можливим пряму заміну
|
|
|
|
|
бібліотек, написаних на мові С на бібліотеки, написані на Rust.
|
|
|
|
|
|
|
|
|
|
Перший реліз Rust (версія 0.1) вийшла в січні 2012 року і з тих пір оновлення
|
|
|
|
|
виходили так часто, що загальною порадою розробникам було не чекати якоїсь
|
|
|
|
|
стабільної версії, а використовувати нічні збірки компілятора.
|
|
|
|
|
|
|
|
|
|
15 травня 2015 року вийшла версія Rust 1.0. Для цієї версії була дана гарантія
|
|
|
|
|
зворотної сумісності. Подальші нічні збірки покращили швидкість компіляції та
|
|
|
|
|
деякі інші аспекти. На даний момент оновлення Rust виходять кожні 6 тижнів.
|
|
|
|
|
Бета-версія Rust 1.1 вийшла одночасно з релізом Rust 1.0.
|
|
|
|
|
|
|
|
|
|
Не зважаючи на те, що Rust є відносно низькорівневою мовою програмування, в
|
|
|
|
|
ній є деякі концепти, притаманні високорівневим мовам. Це робить Rust не лише
|
|
|
|
|
швидким, але й досить зручним та ефективним інструментом розробки.
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
// Це коментар. Він починається в цьому рядку...
|
|
|
|
|
// і продовжується в цьому
|
|
|
|
|
|
|
|
|
|
/// Цей коментар включає в себе документацію і підтримує markdown.
|
|
|
|
|
/// # Приклади
|
|
|
|
|
///
|
|
|
|
|
/// ```
|
|
|
|
|
/// let five = 5
|
|
|
|
|
/// ```
|
|
|
|
|
|
|
|
|
|
///////////////
|
|
|
|
|
// 1. Основи //
|
|
|
|
|
///////////////
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
// Функції
|
|
|
|
|
// `i32` - це 32-бітний цілочислений знаковий тип даних
|
|
|
|
|
fn add2(x: i32, y: i32) -> i32 {
|
|
|
|
|
// неявне повернення результату (в кінці рядку немає крапки з комою)
|
|
|
|
|
x + y
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(unused_variables)]
|
|
|
|
|
#[allow(unused_assignments)]
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
// Головна функція
|
|
|
|
|
fn main() {
|
|
|
|
|
// Числа //
|
|
|
|
|
|
|
|
|
|
// Незмінне число
|
|
|
|
|
let x: i32 = 1;
|
|
|
|
|
|
|
|
|
|
// суфікси для позначення цілого числа та числа з плаваючою змінною
|
|
|
|
|
let y: i32 = 13i32;
|
|
|
|
|
let f: f64 = 1.3f64;
|
|
|
|
|
|
|
|
|
|
// Вивід типів
|
|
|
|
|
// Як правило, Rust може самостійно визначити тип змінної, отож
|
|
|
|
|
// ви можете не прописувати його явно
|
|
|
|
|
// В даному документі типи явно прописані в багатьох місцях, це зроблено
|
|
|
|
|
// виключно в навчальних цілях. В реальному коді вивід типів спрацює
|
|
|
|
|
// в більшості випадків
|
|
|
|
|
let implicit_x = 1;
|
|
|
|
|
let implicit_f = 1.3;
|
|
|
|
|
|
|
|
|
|
// арифметика
|
|
|
|
|
let sum = x + y + 13;
|
|
|
|
|
|
|
|
|
|
// Змінні
|
|
|
|
|
let mut mutable = 1;
|
|
|
|
|
mutable = 4;
|
|
|
|
|
mutable += 2;
|
|
|
|
|
|
|
|
|
|
// Строки //
|
|
|
|
|
|
|
|
|
|
// Строкові літерали
|
|
|
|
|
let x: &str = "Привіт, світ!";
|
|
|
|
|
|
|
|
|
|
// Друк на екран
|
|
|
|
|
println!("{} {}", f, x); // 1.3 Привіт, світ!
|
|
|
|
|
|
|
|
|
|
// `String` – строка, що розміщується в "купі"
|
|
|
|
|
let s: String = "hello world".to_string();
|
|
|
|
|
|
|
|
|
|
// Строковий зріз - це незмінне відображення якоїсь строки (або її частини)
|
|
|
|
|
// Зріз можна розглядати як константну пару покажчиків (на початок та кінець
|
|
|
|
|
// якоїсь строки)
|
|
|
|
|
let s_slice: &str = &s;
|
|
|
|
|
|
|
|
|
|
println!("{} {}", s, s_slice); // Привіт, світ! Привіт, світ!
|
|
|
|
|
|
|
|
|
|
// Вектори/масиви //
|
|
|
|
|
|
|
|
|
|
// Масив фіксованого розміру
|
|
|
|
|
let four_ints: [i32; 4] = [1, 2, 3, 4];
|
|
|
|
|
|
|
|
|
|
// Масив змінного розміру (вектор)
|
|
|
|
|
let mut vector: Vec<i32> = vec![1, 2, 3, 4];
|
|
|
|
|
vector.push(5);
|
|
|
|
|
|
|
|
|
|
// Зріз - незмінне відображення масиву
|
|
|
|
|
// Це схоже на строковий зріз, але в даному випадку мова йде про вектори
|
|
|
|
|
let slice: &[i32] = &vector;
|
|
|
|
|
|
|
|
|
|
// Використовуйте `{:?}` щоб вивести щось в цілях відлагодження
|
|
|
|
|
println!("{:?} {:?}", vector, slice); // [1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
|
|
|
|
|
|
|
|
|
|
// Кортеж //
|
|
|
|
|
|
|
|
|
|
// Кортеж - це набір фіксованого розміру, що включає значення кількох типів
|
|
|
|
|
let x: (i32, &str, f64) = (1, "привіт", 3.4);
|
|
|
|
|
|
|
|
|
|
// розбираємо кортеж "х" на окремі змінні "a", "b" та "с"
|
|
|
|
|
let (a, b, c) = x;
|
|
|
|
|
println!("{} {} {}", a, b, c); // 1 привіт 3.4
|
|
|
|
|
|
|
|
|
|
// доступ по індексу
|
|
|
|
|
println!("{}", x.1); // привіт
|
|
|
|
|
|
|
|
|
|
//////////////
|
|
|
|
|
// 2. Типи //
|
|
|
|
|
//////////////
|
|
|
|
|
|
|
|
|
|
// Структура
|
|
|
|
|
struct Point {
|
|
|
|
|
x: i32,
|
|
|
|
|
y: i32,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let origin: Point = Point { x: 0, y: 0 };
|
|
|
|
|
|
|
|
|
|
// Структура з безіменними полями, "кортежна структура"
|
|
|
|
|
struct Point2(i32, i32);
|
|
|
|
|
|
|
|
|
|
let origin2 = Point2(0, 0);
|
|
|
|
|
|
|
|
|
|
// перелічуваний тип даних
|
|
|
|
|
enum Direction {
|
|
|
|
|
Left,
|
|
|
|
|
Right,
|
|
|
|
|
Up,
|
|
|
|
|
Down,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let up = Direction::Up;
|
|
|
|
|
|
|
|
|
|
// перелічуваний тип даних з полями
|
|
|
|
|
enum OptionalI32 {
|
|
|
|
|
AnI32(i32),
|
|
|
|
|
Nothing,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let two: OptionalI32 = OptionalI32::AnI32(2);
|
|
|
|
|
let nothing = OptionalI32::Nothing;
|
|
|
|
|
|
|
|
|
|
// Узагальнене програмування //
|
|
|
|
|
|
|
|
|
|
struct Foo<T> { bar: T }
|
|
|
|
|
|
|
|
|
|
// Ось так стандартна бібліотека Rust оголошує `Option`
|
|
|
|
|
enum Optional<T> {
|
|
|
|
|
SomeVal(T),
|
|
|
|
|
NoVal,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Методи //
|
|
|
|
|
|
|
|
|
|
impl<T> Foo<T> {
|
|
|
|
|
// Методи приймають неявний параметр `self`
|
|
|
|
|
fn get_bar(self) -> T {
|
|
|
|
|
self.bar
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let a_foo = Foo { bar: 1 };
|
|
|
|
|
println!("{}", a_foo.get_bar()); // 1
|
|
|
|
|
|
|
|
|
|
// Типажі (в інших мовах програмування схожою сутністю є інтерфейси) //
|
|
|
|
|
|
|
|
|
|
trait Frobnicate<T> {
|
|
|
|
|
fn frobnicate(self) -> Option<T>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> Frobnicate<T> for Foo<T> {
|
|
|
|
|
fn frobnicate(self) -> Option<T> {
|
|
|
|
|
Some(self.bar)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let another_foo = Foo { bar: 1 };
|
|
|
|
|
println!("{:?}", another_foo.frobnicate()); // Some(1)
|
|
|
|
|
|
|
|
|
|
/////////////////////////
|
|
|
|
|
// 3. Відповідність шаблону //
|
|
|
|
|
/////////////////////////
|
|
|
|
|
|
|
|
|
|
let foo = OptionalI32::AnI32(1);
|
|
|
|
|
match foo {
|
|
|
|
|
OptionalI32::AnI32(n) => println!("Це тип i32: {}", n),
|
|
|
|
|
OptionalI32::Nothing => println!("Це ніщо!"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Складніший приклад
|
|
|
|
|
struct FooBar { x: i32, y: OptionalI32 }
|
|
|
|
|
let bar = FooBar { x: 15, y: OptionalI32::AnI32(32) };
|
|
|
|
|
|
|
|
|
|
match bar {
|
|
|
|
|
FooBar { x: 0, y: OptionalI32::AnI32(0) } =>
|
|
|
|
|
println!("Числа рівні нулю!"),
|
|
|
|
|
FooBar { x: n, y: OptionalI32::AnI32(m) } if n == m =>
|
|
|
|
|
println!("Числа однакові"),
|
|
|
|
|
FooBar { x: n, y: OptionalI32::AnI32(m) } =>
|
|
|
|
|
println!("Числа різні: {} {}", n, m),
|
|
|
|
|
FooBar { x: _, y: OptionalI32::Nothing } =>
|
|
|
|
|
println!("Друге число - ніщо!"),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////
|
|
|
|
|
// 4. Потік керування //
|
|
|
|
|
/////////////////////
|
|
|
|
|
|
|
|
|
|
// Цикл `for`
|
|
|
|
|
let array = [1, 2, 3];
|
2021-11-01 21:27:42 +00:00
|
|
|
|
for i in array {
|
2019-09-01 07:55:27 +00:00
|
|
|
|
println!("{}", i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Діапазони
|
|
|
|
|
for i in 0u32..10 {
|
|
|
|
|
print!("{} ", i);
|
|
|
|
|
}
|
|
|
|
|
println!("");
|
|
|
|
|
// друкує `0 1 2 3 4 5 6 7 8 9 `
|
|
|
|
|
|
|
|
|
|
// `if`
|
|
|
|
|
if 1 == 1 {
|
|
|
|
|
println!("Математика працює!");
|
|
|
|
|
} else {
|
|
|
|
|
println!("Ой, лишенько...");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `if` як вираз
|
|
|
|
|
let value = if true {
|
|
|
|
|
"добре"
|
|
|
|
|
} else {
|
|
|
|
|
"погано"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Цикл `while`
|
|
|
|
|
while 1 == 1 {
|
|
|
|
|
println!("Всесвіт функціонує стабільно.");
|
|
|
|
|
// Вираз break перериває цикл
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Нескінченний цикл
|
|
|
|
|
loop {
|
|
|
|
|
println!("Привіт!");
|
|
|
|
|
// Вираз break перериває цикл
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////
|
|
|
|
|
// 5. Вказівники і безпека пам'яті //
|
|
|
|
|
/////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Володіючий вказівник - тільки хтось один може "володіти" вказівником в
|
|
|
|
|
// будь-який момент. Це означає, що коли "Box" вийде за межі області
|
|
|
|
|
// видимості - його можна безпечно звільнити
|
|
|
|
|
let mut mine: Box<i32> = Box::new(3);
|
|
|
|
|
*mine = 5; // розіменування `mine` з присвоєнням йому нового значення
|
|
|
|
|
// `now_its_mine` перебирає на себе володіння над `mine`. Іншими словами,
|
|
|
|
|
// `mine` переміщується.
|
|
|
|
|
let mut now_its_mine = mine;
|
|
|
|
|
*now_its_mine += 2;
|
|
|
|
|
|
|
|
|
|
println!("{}", now_its_mine); // 7
|
|
|
|
|
// println!("{}", mine); // цей код не скомпілюється, оскільки тепер
|
|
|
|
|
// покажчиком на дані володіє `now_its_mine`
|
|
|
|
|
|
|
|
|
|
// Посилання – незмінний вказівник на дані
|
|
|
|
|
// При створенні посилання на якесь значення, ми говоримо, що значення
|
|
|
|
|
// було "запозичене". Поки значення є запозиченим - воно не може бути
|
|
|
|
|
// змінене або переміщене. Запозичення пропадає, як тільки стається вихід з
|
|
|
|
|
// області видимості, де було створене посилання
|
|
|
|
|
let mut var = 4;
|
|
|
|
|
var = 3;
|
|
|
|
|
let ref_var: &i32 = &var;
|
|
|
|
|
|
|
|
|
|
println!("{}", var); // На відміну від `mine`, `var` можна використати
|
|
|
|
|
println!("{}", *ref_var);
|
|
|
|
|
// var = 5; // цей код не скомпілюється, оскільки `var` зараз є запозиченим
|
|
|
|
|
// *ref_var = 6; // цей код також не зкомпілюється, оскільки `ref_var`
|
|
|
|
|
// є незмінним посиланням
|
|
|
|
|
|
|
|
|
|
// Змінне посилання
|
|
|
|
|
// Значення можна запозичити з можливістю зміни. У цьому випадку доступ до
|
|
|
|
|
// оригінального значення втрачається.
|
|
|
|
|
let mut var2 = 4;
|
|
|
|
|
let ref_var2: &mut i32 = &mut var2;
|
|
|
|
|
*ref_var2 += 2; // '*' використовується для доступу до змінного посилання
|
|
|
|
|
|
|
|
|
|
println!("{}", *ref_var2); // 6 , // при заміні на var2 код не зкомпілюється
|
|
|
|
|
// ref_var2 має тип &mut i32, отож зберігає посилання на i32, а не значення
|
|
|
|
|
// var2 = 2; // цей рядок не зкомпілюється, оскільки `var2` є запозиченим.
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Матеріали для самовдосконалення
|
|
|
|
|
|
|
|
|
|
В даному матеріалі ми оглянули лише основи Rust. Більше матеріалу ви можете
|
|
|
|
|
знайти на сайті
|
|
|
|
|
[The Rust Programming Language](http://doc.rust-lang.org/book/index.html)
|
|
|
|
|
Також існує Reddit-розділ [/r/rust](http://reddit.com/r/rust). Люди на каналі
|
|
|
|
|
irc.mozilla.org також завжди раді допомогти новачкам.
|
|
|
|
|
|
|
|
|
|
Ви можете спробувати можливості Rust за допомогою онлайн-компілятора на сторінці
|
2024-04-27 03:47:13 +00:00
|
|
|
|
[Rust Playground](https://play.rust-lang.org) або
|
2019-09-01 07:55:27 +00:00
|
|
|
|
[Rust website](http://rust-lang.org).
|