- Katılım
- 7 Ocak 2026
- Mesajlar
- 290
- Tepkime puanı
- 2
- Puanları
- 18
Rust'ta
Fonksiyonlar değerler üzerinde çalışırken, makrolar kodun kendisi üzerinde çalışır. Yani makrolar, henüz kod derlenmeden önce sizin yerinize daha fazla kod yazan "kod üreten kodlar"dır.
Rust
println!, vec! veya panic! gibi ifadelerin sonundaki ünlem işareti (!), bunların normal fonksiyonlar değil, birer makro olduğunu fısıldar.Fonksiyonlar değerler üzerinde çalışırken, makrolar kodun kendisi üzerinde çalışır. Yani makrolar, henüz kod derlenmeden önce sizin yerinize daha fazla kod yazan "kod üreten kodlar"dır.
1. Neden Makro Kullanırız? (Fonksiyonlardan Farkı)
Makroları fonksiyonlardan ayıran üç temel süper güç vardır:- Değişken Sayıda Argüman: Bir fonksiyonun parametre sayısı sabittir, ancak
println!içine istediğiniz kadar değişken atabilirsiniz. - Meta-programlama: Makrolar, derleme aşamasında tip tanımlarını okuyabilir ve otomatik olarak
implblokları (örneğin#[derive(Debug)]) oluşturabilir. - Performans: Makrolar derleme zamanında "açılır" (expand), bu yüzden çalışma zamanında (runtime) bir fonksiyon çağrısı maliyeti getirmezler.
2. Makro Türleri
Rust'ta iki ana makro türü bulunur:A. Bildirimsel Makrolar (Declarative Macros)
En yaygın kullanılan türdür.macro_rules! anahtar kelimesiyle tanımlanırlar. Bir match ifadesine benzer şekilde çalışırlar: Belirli bir kalıba uyan kod gelirse, onu başka bir koda dönüştürürler.Rust
Kod:
macro_rules! selamla {
// Hiç argüman verilmezse
() => {
println!("Merhaba!");
};
// Bir isim verilirse
($isim:expr) => {
println!("Merhaba, {}!", $isim);
};
}
fn main() {
selamla!(); // Çıktı: Merhaba!
selamla!("Dünya"); // Çıktı: Merhaba, Dünya!
}
B. Prosedürel Makrolar (Procedural Macros)
Bu makrolar daha gelişmiştir; girdi olarak aldıkları Rust kodunu bir "token akışı" (token stream) olarak işler ve üzerinde karmaşık değişiklikler yaparlar. Üç çeşittir:- Derive Makroları:
#[derive(Serialize)]gibi, bir struct üzerine otomatik özellik ekler. - Attribute-like:
#[tokio::main]gibi, fonksiyonların davranışını değiştirir. - Function-like:
sqlx::query!(...)gibi, fonksiyon gibi çağrılır ama içinde karmaşık mantıklar (örneğin SQL kontrolü) çalıştırır.
3. println! Makrosunun Sırrı
Nedenprintln bir fonksiyon değildir? Çünkü Rust'ın tip güvenliği (type safety) kuralları, bir fonksiyonun çalışma zamanında format string içindeki {} sayısı ile argüman sayısını kontrol etmesine izin vermez.println! makrosu, derleme anında string'i analiz eder:- Eğer
{}sayısı ile argümanlar uyuşmuyorsa derleme hatası verir. - Argümanların
DisplayveyaDebugtrait'ine sahip olup olmadığını kontrol eder. - Arka planda
std::io::stdout()yazma işlemlerini sizin yerinize optimize ederek kodunuzu genişletir.
4. Makro Yazarken Dikkat Edilmesi Gerekenler
- Okunabilirlik: Makrolar kodun ne yaptığını gizleyebilir, bu yüzden sadece fonksiyonların yetmediği yerde kullanılmalıdır.
- Hata Ayıklama: Makro içindeki hataları bulmak zordur.
cargo expandkomutunu kullanarak makroların arkasında üretilen asıl kodu görebilirsiniz.
Özet Tablo
| Özellik | Fonksiyonlar | Makrolar |
| Sözdizimi | isim() | isim!() |
| Parametreler | Sabit sayıda ve tipte | Değişken sayıda (Variadic) |
| Çalışma Zamanı | Çağrı anında (Runtime) | Derleme anında (Compile-time) |
| Kod Üretimi | Yapamaz | Yapabilir |