1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
|
---
language: Rust
contributors:
- ["P1start", "http://p1start.github.io/"]
translators:
- ["Volodymyr Korniichuk", "https://github.com/ezhikus"]
filename: learnrust-uk.rs
lang: uk-ua
---
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];
for i in array {
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 за допомогою онлайн-компілятора на сторінці
[Rust Playground](https://play.rust-lang.org) або
[Rust website](http://rust-lang.org).
|