Makro ļauj rakstīt kodu, kas raksta citu kodu. Uzziniet par dīvaino un jaudīgo metaprogrammēšanas pasauli.

Koda ģenerēšana ir funkcija, kas atrodama lielākajā daļā mūsdienu programmēšanas valodu. Tas var palīdzēt samazināt standarta kodu un koda dublēšanos, definēt domēnam specifiskas valodas (DSL) un ieviest jaunu sintaksi.

Rust nodrošina jaudīgu makro sistēmu, kas ļauj ģenerēt kodu kompilēšanas laikā sarežģītākai programmēšanai.

Ievads Rust Macros

Makro ir metaprogrammēšanas veids, ko varat izmantot, lai rakstītu kodu, kas raksta kodu. Rustā makro ir koda daļa, kas kompilēšanas laikā ģenerē citu kodu.

Rūsas makro ir spēcīgs līdzeklis, kas ļauj rakstīt kodu, kas kompilēšanas laikā ģenerē citu kodu, lai automatizētu atkārtotus uzdevumus. Rust makro palīdz samazināt koda dublēšanos un palielina koda apkopi un lasāmību.

Varat izmantot makro, lai ģenerētu jebko, sākot no vienkāršiem koda fragmentiem līdz bibliotēkām un ietvariem. Makro atšķiras no Rūsas funkcijas jo tie darbojas ar kodu, nevis datiem izpildes laikā.

instagram viewer

Makro definēšana rūsā

Jūs definēsit makro ar makro_noteikumi! makro. The makro_noteikumi! makro izmanto paraugu un veidni kā ievadi. Rūsa saskaņo modeli ar ievades kodu un izmanto veidni, lai ģenerētu izvades kodu.

Lūk, kā Rust var definēt makro:

makro_noteikumi! pasaki Sveiki {
() => {
println!("Sveika pasaule!");
};
}

fngalvenais() {
pasaki Sveiki!();
}

Kods definē a pasaki Sveiki makro, kas ģenerē kodu, lai izdrukātu "Sveika, pasaule!". Kods atbilst () sintakse pret tukšu ievadi un println! makro ģenerē izvades kodu.

Šis ir makro palaišanas rezultāts galvenais funkcija:

Makro var pieņemt ģenerētā koda ievades argumentus. Šeit ir makro, kas izmanto vienu argumentu un ģenerē kodu ziņojuma drukāšanai:

makro_noteikumi! say_message {
($ziņa: expr) => {
println!("{}", $ziņojums);
};
}

The say_message makro aizņem $ziņa argumentu un ģenerē kodu, lai izdrukātu argumentu, izmantojot println! makro. The ekspr sintakse atbilst argumentam pret jebkuru Rust izteiksmi.

Rūsas makro veidi

Rust nodrošina trīs veidu makro. Katrs no makro veidiem kalpo konkrētiem mērķiem, un tiem ir sava sintakse un ierobežojumi.

Procedūru makro

Procedūru makro tiek uzskatīti par visspēcīgāko un daudzpusīgāko veidu. Procesuālie makro ļauj definēt pielāgotu sintaksi, kas vienlaikus ģenerē Rust kodu. Varat izmantot procesuālos makro, lai izveidotu pielāgotus atvasinātus makro, pielāgotus atribūtiem līdzīgus makro un pielāgotus funkciju makro.

Jūs izmantosit pielāgotus atvasinātos makro, lai automātiski ieviestu struktūras un enum pazīmes. Populāras pakotnes, piemēram, Serde, izmanto pielāgotu atvasināto makro, lai ģenerētu Rust datu struktūru serializācijas un deserializācijas kodu.

Pielāgoti atribūtiem līdzīgi makro ir ērti, lai Rust kodam pievienotu pielāgotas anotācijas. Rocket tīmekļa ietvars izmanto pielāgotu atribūtam līdzīgu makro, lai definētu maršrutus kodolīgi un salasāmi.

Varat izmantot pielāgotām funkcijām līdzīgus makro, lai definētu jaunas Rust izteiksmes vai priekšrakstus. Lazy_static kaste izmanto pielāgotu funkcijai līdzīgu makro, lai definētu slinks-inicializēts statiskie mainīgie.

Tālāk ir norādīts, kā varat definēt procedūras makro, kas definē pielāgotu atvasināto makro.

izmantot proc_macro:: TokenStream;
izmantot citāts:: citāts;
izmantot syn::{DeriveInput, parse_macro_input};

The izmantot direktīvas importē nepieciešamās kastes un tipus Rust procesuālā makro rakstīšanai.

#[proc_macro_derive (MyTrait)]
krogsfnmy_derive_macro(ievade: TokenStream) -> TokenStream {
ļaut ast = parse_macro_input!(input DeriveInput);
ļaut name = &ast.ident;

ļaut gen = citāts! {
impl MyTrait priekš #name {
// ieviešana šeit
}
};

gen.into()
}

Programma definē procesuālo makro, kas ģenerē struktūras vai enum pazīmes ieviešanu. Programma izsauc makro ar nosaukumu MyTrait struct vai enum atvasinātajā atribūtā. Makro aizņem a TokenStream objektu kā ievadi, kas satur kodu, kas parsēts abstraktajā sintakses kokā (AST) ar parse_macro_input! makro.

The nosaukums mainīgais ir atvasinātais struktūras vai enum identifikators, the citāts! Makro ģenerē jaunu AST, kas atspoguļo ieviešanu MyTrait tipam, kas galu galā tiek atgriezts kā a TokenStream Ar iekšā metodi.

Lai izmantotu makro, jums tas ir jāimportē no moduļa, kurā to deklarējāt:

// pieņemot, ka esat deklarējis makro modulī my_macro_module

izmantot mans_makro_modulis:: mans_atvasinātais_makro;

Deklarējot struktūru vai enum, kas izmanto makro, jūs pievienosit #[atvasināt (MyTrait)] atribūts deklarācijas augšpusē.

#[atvasināt (MyTrait)]
struktūraMyStruct {
// lauki šeit
}

Struktūras deklarācija ar atribūtu paplašina līdz implementācijai MyTrait struktūras iezīme:

impl MyTrait priekš MyStruct {
// ieviešana šeit
}

Īstenošana ļauj izmantot metodes MyTrait iezīme ieslēgta MyStruct gadījumiem.

Atribūtu makro

Atribūtu makro ir makro, ko varat lietot Rust vienumiem, piemēram, struktūrām, enums, funkcijām un moduļiem. Atribūtu makro ir atribūts, kam seko argumentu saraksts. Makro parsē argumentu, lai ģenerētu Rust kodu.

Jūs izmantosiet atribūtu makro, lai kodam pievienotu pielāgotas darbības un anotācijas.

Šeit ir atribūtu makro, kas Rust struktūrai pievieno pielāgotu atribūtu:

// makro definīcijas moduļu importēšana
izmantot proc_macro:: TokenStream;
izmantot citāts:: citāts;
izmantot syn::{parse_macro_input, DeriveInput, AttributeArgs};

#[proc_macro_attribute]
krogsfnmy_attribute_macro(attr: TokenStream, vienums: TokenStream) -> TokenStream {
ļaut args = parse_macro_input!(attr AttributeArgs);
ļaut ievade = parse_macro_input!(vienums DeriveInput);
ļaut nosaukums = &input.ident;

ļaut gen = citāts! {
#ievade
impl #name {
// pielāgota uzvedība šeit
}
};

gen.into()
}

Makro uzņem argumentu sarakstu un struktūras definīcija un ģenerē modificētu struktūru ar definētu pielāgoto darbību.

Makro kā ievadi izmanto divus argumentus: atribūtu, kas tiek lietots makro (parsēts ar parse_macro_input! makro) un vienumu (parsēts ar parse_macro_input! makro). Makro izmanto citāts! makro, lai ģenerētu kodu, ieskaitot sākotnējo ievades vienumu un papildu impl bloks, kas nosaka pielāgoto uzvedību.

Visbeidzot, funkcija atgriež ģenerēto kodu kā a TokenStream Ar iekšā () metodi.

Makro noteikumi

Makro noteikumi ir visvienkāršākais un elastīgākais makro veids. Makro kārtulas ļauj definēt pielāgotu sintaksi, kas kompilēšanas laikā tiek paplašināta līdz Rust kodam. Makro kārtulas nosaka pielāgotus makro, kas atbilst jebkurai rūsas izteiksmei vai paziņojumam.

Jūs izmantosiet makro kārtulas, lai ģenerētu standarta kodu, lai abstrakti iegūtu zema līmeņa informāciju.

Lūk, kā Rust programmās varat definēt un izmantot makro kārtulas.

makro_noteikumi! make_vector {
( $( $x: expr ),* ) => {
{
ļautmut v = Vec::jauns();
$(
v.push($x);
)*
v
}
};
}

fngalvenais() {
ļaut v = make_vector![1, 2, 3];
println!("{:?}", v); // izdrukā "[1, 2, 3]"
}

Programma definē a make_vector! makro, kas izveido jaunu vektoru no komatatdalīto izteiksmju saraksta galvenais funkciju.

Makro iekšpusē modeļa definīcija atbilst makrom nodotajiem argumentiem. The $( $x: expr ),* sintakse atbilst visām ar komatu atdalītām izteiksmēm, kas identificētas kā $x.

The $( ) sintakse paplašināšanas kodā atkārto katru izteiksmi argumentu sarakstā, kas nodots makro pēc noslēdzošās iekavas, kas norāda, ka iterācijas jāturpina, līdz makro apstrādā visus izteiksmes.

Efektīvi organizējiet savus rūsas projektus

Rūsas makro uzlabo koda organizēšanu, ļaujot definēt atkārtoti lietojamus koda modeļus un abstrakcijas. Makro var palīdzēt rakstīt kodolīgāku, izteiksmīgāku kodu bez dublēšanās dažādās projekta daļās.

Varat arī sakārtot Rust programmas kastēs un moduļos, lai nodrošinātu labāku koda organizēšanu, atkārtotu izmantošanu un mijiedarbību ar citām kastēm un moduļiem.