Menu

Zero Generics: Fonksiyonlar ve Shape'lerde Type Parametreleri

Zero'da generic'ler nasıl çalışır: fonksiyonlar ve shape'lerde type parametreleri tanımlama, generic fonksiyon çağırma ve uzun parametrelendirmeleri temiz isimlere dönüştüren type-alias deseni.

Bu sayfada çalıştırılabilir editörler var — düzenle, çalıştır ve sonucu anında gör.

Neden Generic'ler

Birden fazla element tipi için çalışması gereken tiplerle hızlıca karşılaşırsınız. İki değerin "pair"ı, değerlerin integer mı, string mi, yoksa kullanıcı tanımlı bir shape mi olduğunu umursamamalı. Generic'ler tipi bir kez yazıp çağıranın ihtiyacına göre istediği element tipleriyle instantiate etmenize olanak verir.

Alternatif — IntPair, StringPair, BytePair ve benzerlerini ayrı ayrı yazmak — hızla sıkıcı hale gelir ve compose etmez. Zero'da generic'ler bu iş için standart araçtır.

Generic Fonksiyonlar

Type parametrelerini fonksiyon adı ile parametre listesi arasında angle bracket'ler içinde bildirin:

fun makePair<T, U>(left: T, right: U) -> Pair<T, U> {
    return Pair { left: left, right: right }
}

T ve U placeholder tipleridir — çağıran ne olduklarına karar verir.

Çağrılar genellikle bunları hecelemeniz gerekmez; compiler argüman tiplerinden çıkarır:

let pair = makePair(40, 2_u8)

Burada T, i32 (suffix'siz bir integer literal için varsayılan) olarak ve U, u8 (_u8 suffix'inden) olarak çıkarılır. Sonuç pair bağlamasının tipi Pair<i32, u8> olur.

Inference yanlış tipleri seçeceği — örneğin literal'ler belirsiz olduğu için — durumda, parametreleri çağrı yerinde sabitleyebilirsiniz:

let pair = makePair<u8, u8>(1, 2)

(Angle-bracket çağrı söz diziminin tam olarak gösterildiği gibi olup olmadığı Zero sürümleri arasında değişebilir; kesin yazım için güncel dokümanlara bakın. Inference-first davranışı kararlı kısımdır.)

Generic Shape'ler

Shape'ler de type parametrelerini aynı şekilde alır:

shape Pair<T, U> {
    left: T,
    right: U,
}

Her alanın tipi parametrelerden söz edebilir. Instance'lar bunları sabitler:

let intBytes: Pair<i32, u8> = Pair { left: 40, right: 2_u8 }
let words:    Pair<String, String> = Pair { left: "hi", right: "there" }

Generic shape ve generic fonksiyonu birleştiren işlenmiş bir örnek — inference'ı iş başında görmek için Run'a tıklayın:

Bir generic shape bildirimi, bir generic fonksiyon, sıkı tiplendirilmiş bir çağrı yeri. IntBytePair boilerplate'i yok.

Type Alias'ları

Aynı parametrelendirilmiş tip tekrar tekrar geldiğinde, ona type ile bir isim verin:

type BytePair = Pair<u8, u8>

Artık BytePair, bir tip yazabileceğiniz her yerde Pair<u8, u8> ile değiştirilebilir:

Bir alias yalnızca bir adlandırma özelliğidir — ayrı bir tip yaratmaz. BytePair alan bir fonksiyon, Pair<u8, u8> tipinde bir değeri seve seve kabul eder (ve tersi).

Standart Kütüphanede Generic'ler

Aynı mekanizma standart kütüphanenin büyük bir kısmını güçlendirir. Gerçek Zero kodunda göreceğiniz birkaçı:

  • Maybe<T> — bir T veya hiçbir şey tutan opsiyonel bir değer.
  • Span<T>T değerleri üzerinde ödünç alınmış bir dilim. Span<u8>, bir byte buffer üzerinde kanonik görünümdür.
  • ref<T> ve mutref<T> — kopyalamadan veri paylaşmanız gereken durumlar için explicit referans tipleri.

Bunların hepsini bir kerede öğrenmek zorunda değilsiniz. Generic'lerin önemi, aynı shape'in elinizdeki hangi element tipi için de çalışmasıdır.

Generic'ler Ne Zaman Karşılığını Verir (ve Ne Zaman Vermez)

Aynı fonksiyonu ya da shape'i iki kez farklı element tipleriyle yazdığınızı fark ettiğinizde generic'lere başvurun. Şu durumlarda somut bir tipe geçin:

  • Fonksiyonun mantığı yalnızca belirli bir tip için anlamlıdır (örneğin String'ler için bir parser).
  • Tipin hata mesajlarında görünmesini istiyorsunuz, böylece debug etmek kolaylaşır.
  • Performans karakteristikleri memory'de belirli bir boyuta bağlıdır.

Generic'lerin maliyeti gerçektir — daha büyük binary'ler (her instantiation yeni kod üretir) ve biraz daha yavaş compile süreleri. Çoğu uygulama kodu için bu maliyet ihmal edilebilir, ama binary boyutunun önemli olduğu sıkı, embedded tarzı kod yazıyorsanız bilmekte fayda var.

Constraint'ler Üzerine Bir Not

Bazı generic sistemleri bir type parametresini sınırlandırmanıza olanak verir ("T =='i desteklemeli", "T Iterator implement etmeli"). Zero'nun pre-1.0'daki constraint hikayesi hâlâ gelişiyor — resmi repo'daki örnekler generic'leri ayrıntılı bounds olmadan düz formda kullanıyor. Dil oturdukça, constraint söz diziminin dilin geri kalanıyla tutarlı küçük ve düzenli bir formda gelmesini bekleyin. Şimdilik, gerçekten geçirdiğiniz her T için çalışan generic'ler yazın ve bir işlemin desteklenmediği durumlarda compiler'ın size söylemesine izin verin.

Sırada: Enum'lar

Generic'ler size tipler üzerinde parametrelendirme imkanı verir. Bir sonraki yapı taşı yelpazenin diğer ucunda — Zero'nun variant'ları ekstra veri taşımayan durumlar için sade enumeration tipi olan enum'lar.

Sıkça Sorulan Sorular

Zero'da generic'ler nasıl çalışır?

Type parametrelerini fonksiyon veya shape adından sonra angle bracket'ler içinde bildirin: fun makePair<T, U>(left: T, right: U) -> Pair<T, U> ya da shape Pair<T, U> { left: T, right: U }. Çağıranlar parametreleri ya explicit olarak sabitler (Pair<i32, u8>) ya da compiler'ın çağrının argümanlarından çıkarmasına izin verir.

Zero'da shape'ler generic olabilir mi?

Evet. Bir shape, fonksiyonlarda kullanılan aynı angle-bracket söz dizimiyle type parametreleri alabilir: shape Pair<T, U> { left: T, right: U }. Her alan tipinde parametreleri kullanabilir. Instance'lar parametrelendirilmiş tipi yazarak oluşturulur — örneğin Pair<i32, u8>.

Generic bir fonksiyonu çağırırken type parametrelerini belirtmek zorunda mıyım?

Genellikle hayır. Compiler bunları argüman tiplerinden çıkarır. makePair(40, 2_u8) çağırmak yeterli — T i32 olur, U ise u8. Inference'ın yanlış tipi seçeceği zaman veya çağrı yerinde belgelemek istediğinizde parametreleri explicit olarak sabitleyebilirsiniz.

Zero'da type alias nedir?

Bir type alias, daha uzun bir tip ifadesi için bir kısaltma adıdır. type BytePair = Pair<u8, u8>, normalde Pair<u8, u8> yazacağınız her yere BytePair yazmanıza olanak verir. Alias saf bir adlandırma özelliğidir — yeni bir tip tanıtmaz, sadece mevcut bir tipe atıfta bulunmanın daha kısa bir yolunu sunar.

Zero'nun standart kütüphanesinde generic'ler nerede görünür?

Her yerde — bir tipin keyfi bir element tipi tutması veya üzerinde işlemesi gereken her yerde. Opsiyonel değerler için Maybe<T>, byte dilimleri için Span<u8>, element tipi üzerinden parametrelendirilmiş container tipleri. Aynı generic mekanizma hem kullanıcı tanımlı hem de standart kütüphane tiplerini halleder.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA