proc_macro cratei
- Rust kursu
- İleri seviye
- Ders 48/81
- 4 dk
proc_macro crate'ini ve temel API'sini tanırsın.
proc_macro crate'i
Prosedürel makrolar, derleme anında çalışan sıradan Rust fonksiyonlarıdır: bir TokenStream alır, yeni bir TokenStream döndürürler. Ayrı bir crate'te, proc-macro = true ile tanımlanmaları gerekir:
# Cargo.toml (makro crate'i)
[lib]
proc-macro = true
// src/lib.rs
use proc_macro::TokenStream;
#[proc_macro_derive(Merhaba)]
pub fn merhaba_turet(girdi: TokenStream) -> TokenStream {
// girdi: struct tanımının belirteçleri
// çıktı: üretilecek impl bloğu
todo!()
}Üç türü vardır: #[derive(..)] makroları, öznitelik makroları (#[route(..)]) ve fonksiyon benzeri makrolar (sql!(..)).
Ne üretir?
#[derive(Merhaba)] struct Kedi; için makronun üreteceği kod, elle yazacağın impl'in aynısıdır. Aynı fikri tek dosyada macro_rules! ile görebiliriz:
trait Merhaba {
fn merhaba() -> String;
}
macro_rules! merhaba_turet {
($t:ident) => {
impl Merhaba for $t {
fn merhaba() -> String {
format!("Merhaba, ben {}", stringify!($t))
}
}
};
}
struct Kedi;
merhaba_turet!(Kedi);Fark: prosedürel makro struct tanımını kendisi okur; burada adı biz veriyoruz.
Uygulama Derive'ın ürettiği
Yukarıdaki Merhaba trait'ini ve merhaba_turet! makrosunu yaz. struct Kedi; ve struct Kopek; için makroyu uygula; iki türün merhaba() sonucunu ayrı satırlara yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
trait Merhaba {
fn merhaba() -> String;
}
macro_rules! merhaba_turet {
($t:ident) => {
impl Merhaba for $t {
fn merhaba() -> String {
format!("Merhaba, ben {}", stringify!($t))
}
}
};
}
struct Kedi;
struct Kopek;
merhaba_turet!(Kedi);
merhaba_turet!(Kopek);
fn main() {
println!("{}", Kedi::merhaba());
println!("{}", Kopek::merhaba());
}Beklenen çıktı
Merhaba, ben Kedi Merhaba, ben Kopek
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Prosedürel makrolar neden ayrı bir crate'te olmalıdır?
- Güvenlik kuralı
- Daha hızlı oldukları için
- Gerekmez
- Derleyici onları önce derleyip kullanan crate'in derlemesi sırasında çalıştırır Doğru cevap
Açıklama: Makro crate'i bir derleyici eklentisi gibi davranır; kendi tanımlandığı crate'in derlenmesi sırasında henüz hazır değildir.
2 Derive bildirimi
#[____(Merhaba)]
pub fn merhaba_turet(girdi: TokenStream) -> TokenStream {
todo!()
}
#[proc_macro_derive(Merhaba)]
pub fn merhaba_turet(girdi: TokenStream) -> TokenStream {
todo!()
}
Açıklama: #[proc_macro_derive(Ad)] bir derive makrosu tanımlar.
3 Makro türü ve örnek
| Kavram | Anlamı |
|---|---|
derive |
#[derive(Serialize)] |
öznitelik |
#[tokio::main] |
fonksiyon benzeri |
sqlx::query!(..) |
bildirimsel |
macro_rules! |