Макроси - це потужна частина інструментарію програміста на Rust, а макроси за прикладом - порівняно простий спосіб скористатися цією потужністю. Тож напишімо один!
Що таке макрос? Вікіпедія описує його так:
Макрос (скорочення від «макроінструкція», від грец. μακρός «довгий») в інформатиці - це правило або закономірність, яка визначає, як певну послідовність вхідних даних (часто послідовність символів) слід відобразити на послідовність вихідних даних для заміни (також часто послідовність символів) згідно з визначеною процедурою. Процес відображення, який інстанціює (перетворює) використання макроса на конкретну послідовність, називається розкриттям макроса.
Дуже пізнавально! Але якщо конкретніше, макроси - це особливий синтаксис, який дає змогу генерувати код під час компіляції. Макроси можна використовувати для обчислень під час компіляції, але частіше це просто ще один спосіб абстрагувати код. Наприклад, ми вже, найпевніше, використовували println!() і vec![]. Кожен із них приймає довільну кількість аргументів, тож ми не можемо виразити їх як прості функції. З іншого боку, вони завжди розкриваються в деяку кількість цілком стандартного коду Rust. Якщо нам цікаво, ми можемо скористатися підкомандою cargo expand, щоб побачити результати розкриття макросів у своєму коді.
Докладніше про макроси в Rust можна прочитати в ґрунтовному розділі книги The Rust Book.
Ми можемо створити Vec довільної довжини прямо на місці за допомогою макроса vec![]. Однак Rust не має вбудованого способу створити HashMap прямо на місці. Виправте це, написавши макрос hashmap!().
Наприклад, користувач нашої бібліотеки міг би написати hashmap!('a' => 3, 'b' => 11, 'z' => 32). Це має розкритися в такий код:
{
let mut hm = HashMap::new();
hm.insert('a', 3);
hm.insert('b', 11);
hm.insert('z', 32);
hm
}
Зауважте, що крейт maplit надає макрос, який цілком розвʼязує цю вправу. Будь ласка, реалізуйте власне рішення замість використання цього крейту; спробуйте впоратися самостійно, перш ніж дивитися його код.