Макрои вам омогућавају да пишете код који пише други код. Сазнајте о чудном и моћном свету метапрограмирања.

Генерисање кода је функција коју ћете наћи у већини модерних програмских језика. Може вам помоћи да смањите шаблонски код и дуплирање кода, дефинишете језике специфичне за домен (ДСЛ) и имплементирате нову синтаксу.

Руст пружа моћан макро систем који вам омогућава да генеришете код у време компајлирања за софистицираније програмирање.

Увод у Руст макрое

Макрои су тип метапрограмирања који можете искористити да напишете код који пише код. У Русту, макро је део кода који генерише други код у време компајлирања.

Руст макрои су моћна функција која вам омогућава да пишете код који генерише други код у време компајлирања за аутоматизацију задатака који се понављају. Руст-ови макрои помажу у смањењу дуплицирања кода и повећању могућности одржавања и читљивости кода.

Макрое можете користити за генерисање било чега, од једноставних исечака кода до библиотека и оквира. Макрои се разликују од Руст функције јер раде на коду, а не на подацима у току извршавања.

instagram viewer

Дефинисање макроа у Русту

Макрое ћете дефинисати помоћу мацро_рулес! макро. Тхе мацро_рулес! макро узима шаблон и шаблон као улаз. Руст усклађује образац са улазним кодом и користи шаблон за генерисање излазног кода.

Ево како можете да дефинишете макрое у Русту:

мацро_рулес! Кажи Здраво {
() => {
принтлн!("Здраво Свете!");
};
}

фнглавни() {
Кажи Здраво!();
}

Код дефинише а Кажи Здраво макро који генерише код за штампање „Здраво, свет!“. Код се подудара са () синтаксу за празан унос и принтлн! макро генерише излазни код.

Ево резултата покретања макроа у главни функција:

Макрои могу узети улазне аргументе за генерисани код. Ево макроа који узима један аргумент и генерише код за штампање поруке:

мацро_рулес! реци_мессаге {
($мессаге: експр) => {
принтлн!("{}", $мессаге);
};
}

Тхе саи_мессаге макро преузима $мессаге аргумент и генерише код за штампање аргумента користећи принтлн! макро. Тхе експр синтакса одговара аргументу против било ког Руст израза.

Типови Руст макроа

Руст пружа три типа макроа. Сваки од типова макроа служи одређеним сврхама, и они имају своју синтаксу и ограничења.

Процедурал Мацрос

Процедурални макрои се сматрају најмоћнијим и најсвестранијим типом. Процедурални макрои вам омогућавају да дефинишете прилагођену синтаксу која истовремено генерише Руст код. Можете да користите Процедуралне макрое да креирате прилагођене макрое за извођење, прилагођене макрое налик атрибутима и прилагођене макрое налик функцијама.

Користићете прилагођене дериве макрое да аутоматски имплементирате структуре и карактеристике енума. Популарни пакети као што је Серде користе прилагођени дериве макро за генерисање кода за серијализацију и десериализацију за Руст структуре података.

Макрои прилагођени атрибутима су згодни за додавање прилагођених напомена у Руст код. Веб оквир Роцкет користи прилагођени макро сличан атрибуту да би концизно и читљиво дефинисао руте.

Можете користити макрое налик прилагођеним функцијама да дефинишете нове Руст изразе или изјаве. Лази_статиц сандук користи прилагођени макро сличан функцији да дефинише лењи-иницијализован статичке променљиве.

Ево како можете да дефинишете процедурални макро који дефинише прилагођени макро:

користити проц_мацро:: ТокенСтреам;
користити цитат:: цитат;
користити син::{ДеривеИнпут, парсе_мацро_инпут};

Тхе користити директиве увозе неопходне сандуке и типове за писање Руст процедуралног макроа.

#[проц_мацро_дериве (МиТраит)]
пубфнми_дериве_мацро(улаз: ТокенСтреам) -> ТокенСтреам {
дозволити аст = парсе_мацро_инпут!(улаз као ДеривеИнпут);
дозволити име = &аст.идент;

дозволити ген = цитат! {
импл МиТраит за #наме {
// имплементација овде
}
};

ген.инто()
}

Програм дефинише процедурални макро који генерише имплементацију особине за структуру или енум. Програм позива макро са именом МиТраит у атрибуту извођења структуре или енума. Макро узима а ТокенСтреам објекат као улаз који садржи код рашчлањен у апстрактно дрво синтаксе (АСТ) са парсе_мацро_инпут! макро.

Тхе име променљива је изведена структура или енум идентификатор, тхе цитат! Макро генерише нови АСТ који представља имплементацију МиТраит за тип који је на крају враћен као а ТокенСтреам са у методом.

Да бисте користили макро, мораћете да увезете макро из модула у којем сте га декларирали:

// под претпоставком да сте декларирали макро у модулу ми_мацро_модуле

користити ми_мацро_модуле:: ми_дериве_мацро;

Када декларишете структуру или енум који користи макро, додаћете #[дериве (МиТраит)] атрибут на врху декларације.

#[дериве (МиТраит)]
струцтМиСтруцт {
// поља овде
}

Декларација структуре са атрибутом се проширује на имплементацију МиТраит особина за структуру:

импл МиТраит за МиСтруцт {
// имплементација овде
}

Имплементација вам омогућава да користите методе у МиТраит особина на МиСтруцт инстанце.

Макрои атрибута

Макрои атрибута су макрои које можете применити на Руст ставке као што су структуре, енуме, функције и модули. Макрои атрибута имају облик атрибута праћеног листом аргумената. Макро анализира аргумент да генерише Руст код.

Користићете макрое атрибута да бисте свом коду додали прилагођена понашања и напомене.

Ево макроа атрибута који додаје прилагођени атрибут Руст структури:

// увоз модула за макро дефиницију
користити проц_мацро:: ТокенСтреам;
користити цитат:: цитат;
користити син::{парсе_мацро_инпут, ДеривеИнпут, АттрибутеАргс};

#[проц_мацро_аттрибуте]
пубфнми_аттрибуте_мацро(аттр: ТокенСтреам, ставка: ТокенСтреам) -> ТокенСтреам {
дозволити аргс = парсе_мацро_инпут!(аттр као АттрибутеАргс);
дозволити улаз = парсе_мацро_инпут!(став као ДеривеИнпут);
дозволити име = &инпут.идент;

дозволити ген = цитат! {
#улазни
импл #наме {
// прилагођено понашање овде
}
};

ген.инто()
}

Макро узима листу аргумената и дефиниција структуре и генерише модификовану структуру са дефинисаним прилагођеним понашањем.

Макро узима два аргумента као улаз: атрибут примењен на макро (рашчлањен са парсе_мацро_инпут! макро) и ставка (рашчлањена са парсе_мацро_инпут! макро). Макро користи цитат! макро за генерисање кода, укључујући оригиналну улазну ставку и додатни импл блок који дефинише прилагођено понашање.

Коначно, функција враћа генерисани код као а ТокенСтреам са у() методом.

Макро правила

Макро правила су најједноставнији и најфлексибилнији тип макроа. Макро правила вам омогућавају да дефинишете прилагођену синтаксу која се проширује на Руст код у време компајлирања. Макро правила дефинишу прилагођене макрое који се подударају са било којим изразом руст или наредбом.

Користићете правила макроа за генерисање шаблонског кода за апстрактну детаље ниског нивоа.

Ево како можете да дефинишете и користите макро правила у својим Руст програмима:

мацро_рулес! маке_вецтор {
( $( $к: експр ),* ) => {
{
дозволитимут в = Вец::Нова();
$(
в.пусх($к);
)*
в
}
};
}

фнглавни() {
дозволити в = маке_вецтор![1, 2, 3];
принтлн!("{:?}", в); // исписује "[1, 2, 3]"
}

Програм дефинише а маке_вецтор! макро који креира нови вектор са листе израза раздвојених зарезима у главни функција.

Унутар макроа, дефиниција шаблона одговара аргументима прослеђеним макроу. Тхе $( $к: експр),* синтакса одговара свим изразима раздвојеним зарезима идентификованим као .

Тхе $( ) синтакса у коду проширења понавља сваки израз на листи аргумената прослеђених макроу после завршну заграду, што указује да итерације треба да се наставе све док макро не обради све изрази.

Организујте своје Руст пројекте ефикасно

Руст макрои побољшавају организацију кода омогућавајући вам да дефинишете обрасце и апстракције кода за вишекратну употребу. Макрои вам могу помоћи да напишете сажетији, изражајнији код без дуплирања у различитим деловима пројекта.

Такође, Руст програме можете организовати у сандуке и модуле за бољу организацију кода, поновну употребу и међуоперацију са другим сандуцима и модулима.