CodeBlanks Logo Icon CodeBlanks

derive macro

Özel bir derive makrosu yazıp test edersin.

Bitirme görevi: derive makrosu

Kendi #[derive(Tanimla)] makronun üreteceği kodu tasarla: struct'ın adını ve her alanı Display ile yazan bir tanim() metodu. Gerçek makroda syn ile alanlar okunur ve quote! ile şu üretilir:

impl Kisi {
    fn tanim(&self) -> String {
        let mut s = String::from("Kisi { ");
        s.push_str(&format!("ad: {}", self.ad));
        s.push_str(", ");
        s.push_str(&format!("yas: {}", self.yas));
        s.push_str(" }");
        s
    }
}

Alıştırmada struct tanımını alan bir macro_rules! ile aynı kodu üreteceğiz.

macro_rules! ile üretim

Tekrar kalıbı her alan için bir parça üretir; join ayraçları yerleştirir:

macro_rules! tanimlanir {
    (struct $ad:ident { $($alan:ident : $tur:ty),* $(,)? }) => {
        struct $ad { $($alan: $tur),* }
        impl $ad {
            fn tanim(&self) -> String {
                let parcalar: Vec<String> = vec![
                    $(format!("{}: {}", stringify!($alan), self.$alan)),*
                ];
                format!("{} {{ {} }}", stringify!($ad), parcalar.join(", "))
            }
        }
    };
}

self.$alan, makro değişkeniyle alan erişimi üretir.

Uygulama Tanımlanabilir struct

Yukarıdaki tanimlanir! makrosunu yaz ve struct Kisi { ad: String, yas: u32 } tanımını onunla üret. Kisi { ad: "Ece".into(), yas: 30 }.tanim() sonucunu yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
macro_rules! tanimlanir {
    (struct $ad:ident { $($alan:ident : $tur:ty),* $(,)? }) => {
        struct $ad {
            $($alan: $tur),*
        }
        impl $ad {
            fn tanim(&self) -> String {
                let parcalar: Vec<String> = vec![
                    $(format!("{}: {}", stringify!($alan), self.$alan)),*
                ];
                format!("{} {{ {} }}", stringify!($ad), parcalar.join(", "))
            }
        }
    };
}

tanimlanir!(struct Kisi { ad: String, yas: u32 });

fn main() {
    let k = Kisi { ad: "Ece".into(), yas: 30 };
    println!("{}", k.tanim());
}

Beklenen çıktı

Kisi { ad: Ece, yas: 30 }

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Alanlar arasındaki virgülü doğru koymanın en kolay yolu nedir?

  • Her alandan sonra virgül yazıp sonuncuyu silmek
  • Virgül kullanmamak
  • Makroda mümkün değil
  • Parçaları bir Vec<String>'e toplayıp join(", ") ile birleştirmek Doğru cevap

Açıklama: join, ayraç sorununu sıfır ve tek eleman durumları dahil doğru çözer.

2 Alan erişimi üret

Soru
$(format!("{}: {}", stringify!($alan), self.____)),*
Cevap
$(format!("{}: {}", stringify!($alan), self.$alan)),*

Açıklama: self.$alan her alan için ayrı bir erişim üretir.

3 Parça ve rolü

Kavram Anlamı
stringify!($ad) Struct adı
stringify!($alan) Alan adı
self.$alan Alan değeri
join(", ") Ayraçlar

İleri seviye bölümündeki tüm dersler