Bir Fonksiyonun Anatomisi
Bir Zero fonksiyonunun genel şekli:
fun name(param1: Type1, param2: Type2) -> ReturnType {
// gövde
return value
}
Parçalar:
fun— fonksiyonu başlatan anahtar kelime.name— fonksiyonun adı.(param1: Type1, ...)— parametre listesi. Her parametrenin explicit bir tipi var.-> ReturnType— dönüş tipi.{ ... }— gövde, ifadelerden oluşan bir blok.return value—valueile fonksiyondan çıkar.
Küçük somut bir örnek:
fun double(value: i32) -> i32 {
return value * 2
}
İşte bütün fonksiyon. Bir i32 alır, başka bir i32 döner, I/O yapmaz. Gövdenin içinden value, let benzeri bir bağlamadır — başka herhangi bir lokal gibi kullanabilirsiniz.
Fonksiyon Çağırma
Çağrılar tam beklediğiniz gibi görünür:
let result = double(21)
Argüman, parametre tipiyle eşleşmek zorunda. Sonuç result'a bağlanır; compiler bunun i32 olduğunu çıkarır çünkü double i32 döndürüyor.
Bir yardımcı ile bir main'i bir araya getiren işlenmiş bir örnek — iş başında görmek için Run'a tıklayın:
Stdout'ta math works\n almalısınız.
pub ve Visibility
Varsayılan olarak, bir dosyada tanımlanan bir fonksiyon o dosyaya (veya modüle — projeler büyüdükçe visibility kuralları sıkılaşır) private olur. Bir fonksiyonu modülünün dışına açmak için önüne pub koyun:
pub fun greet() -> String {
return "hello\n"
}
pub olmadan, diğer modüllerdeki kod greet'i çağıramaz. Runtime, kullanıcı tanımlı bir modülün dışından main'i çağırmak zorundadır, bu yüzden main her zaman pub.
Default-private kuralına yaslanmak iyi bir alışkanlık. Yalnızca arayüz olmasını istediğiniz şeyi işaretleyin; gerisi modül içinde kalsın.
Dönüş Tipleri
Her fonksiyon dönüş tipini -> sonrasında bildirir. Yaygın dönüş tipleri:
fun answer() -> i32 { return 42 }
fun ok() -> bool { return true }
fun label() -> String { return "ready\n" }
fun nothing() -> Void { }
Void, bir değer üretmek yerine side effect'leri üzerinden iş gören fonksiyonlar için dönüş tipidir. Bir Void fonksiyonu explicit bir return'e ihtiyaç duymaz — gövdenin sonundan düşmek yeterli.
fun log(world: World, message: String) -> Void raises {
check world.out.write(message)
}
Değeri Discard Eden Fonksiyon Çağrıları
Bir fonksiyon değer döndürürse ve umursamıyorsanız, dönüşü yine de kabul etmek zorundasınız. Deyim, onu let ile bağlamaktır:
ignored, fonksiyonun geri kalanının asla okumadığı bir bağlama. ignored (ya da _) ismini kullanmanın konvansiyonu, discard'ın bilinçli olduğuna işaret eder. Bu, bir dönüş değerini sessizce düşürmekten daha fazla sürtünme yaratır — ki amaç da bu: ajanların kodu okuyup ürettiği bir dilde, okunmayan bir değer çoğu zaman gün yüzüne çıkması gereken bir bug'dır.
raises'in Rolü
Başarısız olabilen bir fonksiyon bunu imzasında bildirir. Bunu main'de gördük:
pub fun main(world: World) -> Void raises {
check world.out.write("hello\n")
}
raises clause çıplak (herhangi bir hata) ya da spesifik olabilir:
fun validate(ok: Bool) -> i32 raises { InvalidInput } {
if ok == false {
raise InvalidInput
}
return 42
}
raises { InvalidInput }, "bu fonksiyon InvalidInput ile başarısız olabilir, başka hiçbir şeyle değil" anlamına gelir. Çağıranlar hatayı yansıtmak veya ele almak için check (ya da daha karmaşık bir handling formu) kullanmak zorundadır.
Raises ve Check bunu, birden çok error tipinde ne olduğunu ve check'in çağıranın raises clause'u ile nasıl etkileşime girdiğini de dahil olarak derinlemesine işliyor.
Generic Fonksiyonlar
Bir fonksiyonun birden fazla tip üzerinde çalışmasını istediğinizde, angle bracket'ler içinde type parametreleri bildirin:
fun makePair<T, U>(left: T, right: U) -> Pair<T, U> {
return Pair { left: left, right: right }
}
T ve U type parametreleridir — çağıran ne olduklarına karar verir. makePair(40, 2_u8) çağırmak size bir Pair<i32, u8> verir. Generic shape'ler ve constraint'ler de dahil tüm hikaye için Generics sayfasına bakın.
Fonksiyonlar Nerede Yaşar
Küçük bir programda fonksiyonları doğrudan .0 dosyanıza yazarsınız. Bir pakette ise fonksiyonları src/ altında dosyalara yayar ve compiler dosyalar arası referansları sizin yerinize çözer. Temel kısımlar — fun, parametreler, dönüş tipi, gövde — fonksiyonun fiziksel olarak nerede yaşadığından bağımsızdır.
Stil Notları
Resmi örneklerde göreceğiniz birkaç konvansiyon:
- Küçük harf fonksiyon adları, sözcükler bitişik (
makePair) ya da camelCase ile ayrılmış. Standart kütüphane camelCase'e yatkın. - Fonksiyon başına bir dönüş değeri. Birden çok şey döndürmeniz gerekiyorsa onlar için küçük bir
shapekurun — bu, tuple-of-pair-of-tuple döndürmekten daha nettir. Voidfonksiyonları yalnızcacheckçağrıları yapar; değer hesaplayan fonksiyonlar mümkünse I/O'dan kaçınır. Bu ayrım kısmen kültürel kısmen zorunlu — pure bir hesaplama fonksiyonuworldalmaz ve dolayısıyla literal olarak I/O yapamaz.
Son nokta üzerine durmaya değer. I/O World capability'sinin arkasında yaşar ve World explicit olarak geçirildiği için, bir fonksiyonun imzası size I/O yapıp yapmayacağını söyler. İmzalarında World'ten söz etmeyen fonksiyonlar, dış dünyaya göre pure'dur. Bu, ajanların (ve insanların) gövdeyi okumadan güvenebileceği bir özellik.
Sırada: If/Else
Geçerken if'i gördünüz — bir sonraki yazı if/else ifadelerini detaylı ele alıyor; bağlamalarla nasıl etkileştiklerini ve bilinçli olarak neyin eksik olduğunu (truthy coercion yok, ternary yok) içeriyor.
Sıkça Sorulan Sorular
Zero'da bir fonksiyonu nasıl tanımlarım?
fun kullanın: fun name(param: Type) -> ReturnType { body }. Fonksiyonu modülünün dışından görünür yapmak için önüne pub ekleyin. Fonksiyon başarısız olabiliyorsa dönüş tipinden sonra raises ekleyin. Örneğin: pub fun double(value: i32) -> i32 { return value * 2 }.
pub anahtar kelimesi ne yapar?
pub anahtar kelimesi ne yapar?pub bir bildirimi public olarak işaretler — mevcut modülünün dışındaki kodlar tarafından görünür hale getirir. pub olmadan bir fonksiyon, tanımlandığı dosya (ya da pakete) private olur. Geleneksel giriş noktası pub fun main'in public olması gerekir ki runtime onu bulup çağırabilsin.
Zero'da bir fonksiyondan değer nasıl döndürülür?
Fonksiyon gövdesinin içinde return value yazın. İfade, bildirilen dönüş tipiyle eşleşmelidir. Dönüş tipi Void olan bir fonksiyon hiçbir şey döndürmez ve explicit bir return ifadesine ihtiyaç duymaz — gövdenin sonundan düşmek yeterlidir.
Zero fonksiyonları birden fazla parametre alabilir mi?
Evet. Parantez içinde virgülle ayırarak listeleyin, her birinin adı ve tipiyle: fun add(a: i32, b: i32) -> i32 { return a + b }. Her parametre fonksiyon gövdesinde let benzeri bir bağlamadır. Zero, parametrelerde explicit tip ister — fonksiyon tanımlarında parametre tipi inference'ı yoktur.
Fonksiyon imzasında raises ne anlama gelir?
raises ne anlama gelir?raises, fonksiyonun başarısız olabileceğini bildirir. Çıplak raises herhangi bir hata tipine izin verir; raises { InvalidInput } fonksiyonu sadece belirli bir error ile başarısız olabilecek şekilde sınırlar. Çağıranlar başarısızlık olasılığını check (ya da başka bir explicit handling formu) ile kabul etmek zorundadır — onu sessizce yok sayamazlar.