syn ve quote
- Rust kursu
- İleri seviye
- Ders 51/81
- 4 dk
syn ve quote crate'lerini kullanarak kod üretirsin.
syn ve quote
Prosedürel makro yazmanın iki temel aracı:
syn:TokenStream'i Rust sözdizimi ağacına (DeriveInput,ItemFn,Expr...) ayrıştırır.quote:quote! { .. }içinde yazılan Rust kodunu,#değişkenyerleştirmeleriyle birlikte yenidenTokenStream'e çevirir.
let ad = &ast.ident; // syn::Ident: Kisi
let n = alanlar.len();
let uretilen = quote! {
impl #ad {
fn alan_sayisi() -> usize { #n }
}
};Ara adımda kod bir metin değil, yapılandırılmış belirteçlerdir; bu sayede hata mesajları doğru kaynak konumunu gösterir.
Kod üretimini metinle görmek
quote!'in ürettiğini, aynı şablonu metinle kurarak görebiliriz; makro hata ayıklamasında cargo expand da tam olarak bunu gösterir:
fn impl_uret(ad: &str, alanlar: &[&str]) -> String {
format!(
"impl {ad} {{ fn alan_sayisi() -> usize {{ {} }} }}",
alanlar.len()
)
}Gerçek makrolarda metin birleştirme yerine quote! kullanılır; metin yaklaşımı tırnak, kaçış ve konum bilgisi sorunlarına açıktır.
Uygulama Şablondan kod
Yukarıdaki impl_uret fonksiyonunu yaz. impl_uret("Kisi", &["ad", "yas"]) sonucunu yazdır.
Başlangıç kodu
fn main() {
// buraya yaz
}Örnek çözüm
fn impl_uret(ad: &str, alanlar: &[&str]) -> String {
format!(
"impl {ad} {{ fn alan_sayisi() -> usize {{ {} }} }}",
alanlar.len()
)
}
fn main() {
println!("{}", impl_uret("Kisi", &["ad", "yas"]));
}Beklenen çıktı
impl Kisi { fn alan_sayisi() -> usize { 2 } }
Soru ve cevaplar
Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.
1 Makroda kullanıcı hatası (örneğin enum'a uygulanmış struct makrosu) nasıl bildirilmeli?
- syn::Error::new_spanned(..).to_compile_error() ile doğru konumda derleme hatası Doğru cevap
- panic!
- Sessizce boş çıktı
- println!
Açıklama: panic de derleme hatası verir ama konumu belirsizdir; span'li hata kullanıcıyı doğru satıra götürür.
2 Değişken yerleştir
quote! {
impl ____ad {
fn alan_sayisi() -> usize { #n }
}
}
quote! {
impl #ad {
fn alan_sayisi() -> usize { #n }
}
}
Açıklama: quote! içinde #ad, ad değişkenini koda yerleştirir.
3 Araç ve çıktısı
| Kavram | Anlamı |
|---|---|
syn::parse_macro_input! |
Sözdizimi ağacı |
quote! |
TokenStream |
cargo expand |
Açılmış kod |
syn::Error |
Konumlu hata |