🌌 Мова опису ворожих вузлів — Периметр «ТехНови» описується enum-станами вузлів — і С.І.Д. з видимим захватом показує улюблений трюк: якщо з'явиться новий тип вузла, а десь у коді про нього забудуть, компілятор сам укаже на кожне місце, де треба дописати обробку, замість того, щоб мовчки пропустити його в рантаймі.
У багатьох мовах enum — це просто набір іменованих цілочисельних констант.
У Rust enum — це алгебраїчний тип даних (algebraic data type, ADT), де
кожен варіант може нести власні, різні за формою дані. enum NodeStatus { Active, Suspicious(u32), Compromised { by: String, at: u64 } } описує три
принципово різні форми стану: без даних, з одним неозначеним значенням і
зі структурою з іменованими полями — все в одному типі. Це радикально
відрізняється від enum-int у C чи Java: тут варіант і його дані нероздільні,
і компілятор знає точний набір можливих форм значення цього типу — не більше
й не менше, ніж перелічено.
Основний спосіб «розпакувати» enum і дістатися даних усередині варіанта —
конструкція match. Ключова гарантія Rust: match над enum повинен бути
вичерпним (exhaustive) — тобто охоплювати абсолютно всі можливі варіанти,
інакше компіляція не відбудеться з помилкою non-exhaustive patterns (або
зазначить конкретно, які варіанти пропущено). Розробнику не потрібно
пам'ятати весь список варіантів напам'ять і сподіватися, що він нічого не
забув, — компілятор зробить цю перевірку за нього автоматично й безкоштовно
для кожного match у кодовій базі.
Саме тут проявляється ключова педагогічна й інженерна перевага цього
підходу порівняно з, наприклад, if/else ланцюжком по цілочисельному коду
статусу: коли до enum додається новий варіант (скажімо, Quarantined),
кожен match у всій кодовій базі, який раніше вичерпно обробляв старий
набір варіантів, миттєво перестає компілюватися — компілятор буквально
вказує на кожне місце в коді, де потрібно дописати обробку нового випадку.
Це перетворює «забув обробити новий стан десь у величезному проєкті» — типову
причину прихованих багів у динамічних чи слабко типізованих системах — на
помилку компіляції, яку неможливо не помітити.
match підтримує потужні патерни, що виходять за межі простого
перерахування варіантів: деструктуризацію вкладених даних просто в патерні
(Compromised { by, at } if at > threshold => ... — з умовою-guard),
зв'язування частини значення через @ (Suspicious(n @ 100..=200) => ...),
і навмисний «викид» вичерпності через _ => ... (яка варта уваги: додавання
_ глушить майбутню перевірку компілятора для нових варіантів — це свідома
відмова від однієї з головних переваг механізму, тому вважається практикою,
якої варто уникати, якщо є спосіб перелічити варіанти явно).
Крім match, з Rust 1.65+ доступна коротша форма if let для випадку,
коли цікавить лише один варіант (if let NodeStatus::Compromised { by, .. } = status { ... }), і let else для «розпакувати або вийти» (let NodeStatus::Active = status else { return; };). Обидві конструкції — не
альтернативи вичерпності, а зручні скорочення для типового підмножини
сценаріїв match, які самі по собі не вимагають обробки всіх варіантів,
оскільки явно описують «а якщо не цей варіант — роби щось інше/просто вийди».
Прочитати розділи «Enums» та «The match Control Flow Construct» у The Rust Book; додати новий варіант до наявного enum і подивитися, які блоки match компілятор позначить як неповні (помилка non-exhaustive patterns).
Що станеться під час компіляції, якщо в match над enum із чотирма варіантами обробити лише три й не додати гілку _ => ...?
NodeStatus варіант Quarantined { block: &'static str, floor: i8 } і сконструюй його як Quarantined { block: "Б-7", floor: -3 } — компілятор чесно перелічить усі match, які про мінус третій ще не знають. С.І.Д. каже, що «ТехНова» такого варіанта ніколи не оголошувала: у їхньому коді того поверху офіційно не існує. Саме тому він і збирається туди.Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.
cargo buildtarget/debug/; --release — з оптимізаціями у target/release/.cargo💡 Прочитати README прямо в терміналі: cat README.md (виведе весь файл) або less README.md (посторінково; вихід — клавіша q).
Довідка з будь-якої команди: man curl (повний посібник, вихід — q) або коротко curl --help; для підкоманд — docker run --help, cargo build --help.