Rust'ta makrolar, derleme aşamasında kod üretmeye olanak tanır ve metaprogramlama, boilerplate azaltma ve DSL uygulamaları için güçlü araçlar sağlar. Ana makro türleri:
macro_rules!.#[derive], nitelik tabanlı (#[some_macro]) ve fonksiyon gibi (custom_macro!()) alt türlere ayrılır.Declarative makrolar, şablon kod için daha kolaydır; procedural makrolar ise sözdizimi ve tokene analiz üzerinde daha fazla kontrol sağlar.
Declarative makroya bir örnek:
macro_rules! vec_of_strings { ($($x:expr),*) => { { let mut v = Vec::new(); $(v.push($x.to_string());)* v } }; } let v = vec_of_strings!("a", "b"); // => Vec<String>
Procedural makro (derive örneği):
#[derive(Debug, Clone)] struct MyStruct; // Debug derive işlemi std'de procedural makro olarak gerçekleştirilmiştir.
Rust makroları, sözdizimsel olarak hatalı kod veya çalışma zamanında hatalar içeren kod üretebilir mi?
Cevap: Evet, makrolar yazım anında genişletme doğruluğunu kontrol etmez; hatalar yalnızca makronun derleyici tarafından yerleştirilmesinden sonra ortaya çıkabilir. Declarative makrolar, belirsiz sözdizimsel hatalara yol açabilir. Procedural makrolar, hatalı veya savunmasız kod üretebilir, bu nedenle düzgün çalışma testlerinin titizlikle yapılması kritik öneme sahiptir.
Örnek:
macro_rules! make_error { () => { let x = ; // makro kullanıldığında sözdizim hatası oluşacaktır } }
Hikaye
Büyük bir projede boilerplate'i azaltmak için macro_rules! kullanıldı, tüm desen durumları kapsanmadan. Kullanıcı, makroya desteklenmeyen bir ifade geçti ve bu durum karmaşık bir derleme hatasına yol açtı; hatanın kaynağını izlemek zordu.
Hikaye
Procedural makroların crate arasında taşınmasında TokenStream API'sinin sürüm uyumsuzluğu sorunları ortaya çıktı, bu da IDE'nin donmasına neden oldu ve hata sadece no_std derlemelerinde ortaya çıktı.
Hikaye
Procedural makro ile yapılandırmalar için bir DSL yazarken, giriş tokenlerinin güvensiz bir şekilde ayrıştırılması (tip doğrulamasız) sonucunda çalışma zamanında garip hatalar, güvenlik açıkları ve yeni işlevselliğin düzgün bir şekilde dağıtımını engelleyen sorunlar ortaya çıktı.