Genelleştirilmiş (Generic) Fonksiyonlar
Rust, algoritmaları veya veri yapılarını (sıralama veya ikili ağaç gibi) kullanılan veya depolanan türler üzerinde soyutlamanıza olanak tanıyan genelleştirmeleri (generics) destekler.
fn pick<T>(cond: bool, left: T, right: T) -> T { if cond { left } else { right } } fn main() { println!("bir sayı seçildi: {:?}", pick(true, 222, 333)); println!("bir dize seçildi: {:?}", pick(false, 'L', 'R')); }
-
Genelleştirmelerin (generics) kod tekrarını nasıl azaltabileceğini göstermek için genelleştirilmiş
pick
’ten önce veya genelleştirmelerden sonra tek biçimli hâle getirmenin (monomorphization) nasıl çalıştığını göstermek içinpick
’in tek biçimli hâle getirilmiş (monomorphized) sürümlerini göstermek faydalı olabilir.#![allow(unused)] fn main() { fn pick_i32(cond: bool, left: i32, right: i32) -> i32 { if cond { left } else { right } } fn pick_char(cond: bool, left: char, right: char) -> char { if cond { left } else { right } } }
-
Rust, argümanların ve geri dönüş değerinin türlerine dayanarak T için bir tür çıkarır (infers).
-
Bu örnekte
T
için yalnızca ilkel (primitive)i32
vechar
türlerini kullanıyoruz, ancak burada kullanıcı tanımlı türler (user-defined types) de dahil olmak üzere herhangi bir türü kullanabiliriz:struct Foo { val: u8, } pick(false, Foo { val: 7 }, Foo { val: 99 });
-
Bu, C++ şablonlarına (templates) benzer, ancak Rust, genelleştirilmiş (generic) fonksiyonu kısmen de olsa anında derler, bu nedenle bu fonksiyon kısıtlamalarla (constraints) eşleşen tüm türler için geçerli olmalıdır. Örneğin,
cond
yanlışsaleft + right
geri döndürmek içinpick
’i değiştirmeyi deneyin. Yalnızca tamsayılarlapick
örneği kullanılsa bile, Rust bunu yine de geçersiz kabul eder. C++ bunu yapmanıza izin verirdi. -
Genelleştirilmiş (generic) kod, çağrıldığı yerlerde (call sites) genelleştirilmemiş (özelleştirilmiş) koda dönüştürülür. Bu, sıfır maliyetli bir soyutlamadır: soyutlama olmadan veri yapılarını elle kodlamış olsaydınız alacağınız sonucun aynısını elde edersiniz.