saQut, üç tip üzerinde bir dizi yerleşik fonksiyon sağlar: string’ler,
diziler ve struct’lar. Bunları ne import edersiniz ne de tanımlarsınız; her
zaman kullanıma hazırdır. Bu sayfa her birini çalıştırılabilir bir örnekle
belgeler.
Daha önce “metot” kullanmadıysanız bir sonraki bölümden başlayın. Yalnızca
imzalar için hızlı referans tablolarına atlayın.
Yerleşik bir fonksiyonu nokta çağrısı sözdizimiyle çağırırsınız: değeri,
bir noktayı, metot adını ve varsa ek argümanları parantez içinde yazın:
string name ="saqut";
print(name.upper()); // "SAQUT"
Bunu şöyle okuyun: “name’i al, üzerine upper uygula.” Noktanın solundaki
değer, fonksiyonun üzerinde çalıştığı şeydir; parantez içindekiler ek
argümanlardır:
string s ="hello world";
print(s.replace("world", "saQut")); // s değer; "world" ve "saQut"
// ise iki argüman
Nesne yönelimi değil. Buradaki nokta yalnızca kullanışlı bir sözdizimidir.
saQut’ta OOP anlamında sınıf, nesne veya tiplere bağlı metot yoktur.
name.upper(), soldan sağa okunan sıradan bir fonksiyon çağrısının
kısaltmasıdır.
Çoğu string yerleşiği yeni bir değer döndürdüğü için çağrıları
zincirleyebilirsiniz; her sonuç bir sonraki noktaya akar:
saQut’ta string’ler değişmezdir (immutable): bu fonksiyonların hiçbiri
orijinal string’i değiştirmez. Hepsi yeni bir string (veya sayı/bool)
döndürür. Sonucu saklamak isterseniz bir değişkene atayın.
string s ="hello";
s.upper(); // "HELLO" hesaplanır ama ÇÖPE ATILIR, s değişmez
s = s.upper(); // İŞTE böyle saklanır, artık s "HELLO"
String’deki byte sayısını sayar. Düz İngilizce/ASCII metin için bir byte =
bir karakter olduğundan beklediğiniz sonucu verir.
UTF-8 tuzağı. saQut metni UTF-8 olarak saklar; ASCII olmayan karakterler
birden fazla byte tutar. length()görünen karakter sayısını değil, byte
sayısını döndürür:
print("café".length()); // 5, 4 değil; 'é' 2 byte
Saf ASCII metin için bunu göz ardı edebilirsiniz. Uluslararası metinlerde
length(), substring() ve charAt() fonksiyonlarının hep byte
cinsinden çalıştığını unutmayın.
Bu fonksiyonun açıklanmaya değer daha fazla davranışı var; bu yüzden tüm
detaylarıyla anlatıyoruz.
replace, string içinde eski’nin her geçtiği yeri bulur ve her birini
yeni ile değiştirip yeni bir string döndürür. Orijinal değişmez.
string s ="the cat sat on the mat";
string r = s.replace("at", "og");
print(r); // "the cog sog on the mog"
print(s); // "the cat sat on the mat", orijinal aynı
Ne oldu adım adım: replace("at", "og") metni taradı ve c-at, s-at,
m-at içindeki "at"’leri bulup her birini "og" ile değiştirerek cog,
sog, mog yaptı. the kelimesinde at olmadığı için aynen kaldı.
Tüm eşleşmeleri değiştirir, yalnızca ilkini değil. Eğer yalnızca ilkini
değiştirmek isterseniz replace doğru araç değildir; her zaman tümünü değiştirir.
Eşleşmeler çakışmaz. Bir eşleşme değiştirildikten sonra tarama, eklenen
metnin sonundan devam eder; yeni metin tekrar taranmaz:
print("aaa".replace("aa", "b")); // "ba", ilk "aa"→"b", bir "a" arttı
Pratik bir örnek: bir cümleyi URL dostu hale getirmek:
string title ="Hello World Post";
string slug = title.lower().replace("", "-");
print(slug); // "hello-world-post"
Zincirlemeye dikkat: title.lower() bir string döndürür ve biz hemen
sonucun üzerinde .replace(...) çağırırız. Her çağrı yeni bir string
döndürdüğü için soldan sağa sıralayabilirsiniz.
İkinci argümanı dikkatli okuyun. Bu bir uzunluktur (adet), bitiş
konumu değildir. substring(2, 3) “2. indisten başla ve 3 karakter al”
demektir; “2’den 3’e kadar” değildir.
indis byte konumundaki (0’dan başlar) tek karakterlik bir string döndürür.
saQut’ta ayrı bir “tek karakter” tipi yoktur, sonuç 1 uzunluklu bir string’tir.
string s ="saqut";
print(s.charAt(0)); // "s"
print(s.charAt(4)); // "t"
Bir string üzerinde karakter karakter döngü (ASCII):
parca’yı arar ve ilk geçtiği byte indisini döndürür. parca
bulunamazsa null döner; bu yüzden sonuç tipi int? (nullable)
olur. Sayıyı kullanmadan önce null kontrolü yapmalısınız.
string s ="hello world";
int? at =s.indexOf("world");
if (at != null) {
print(at); // 6
}
int? missing =s.indexOf("xyz");
if (missing == null) {
print("bulunamadı");
}
null dönmesi (C’deki -1 geleneğinin aksine), “bulunamadı” durumunun
gerçek bir indis sanılarak sessizce geçiştirilmesini engeller; derleyici sizi
bu durumu ele almaya zorlar.
Diziler referans tipidir; bu fonksiyonların bir kısmı diziyi yerinde
değiştirir (aşağıda “değiştirir” diye işaretlenmiştir). Diziler
paylaşıldığı için, yerinde yapılan bir değişiklik aynı diziyi gösteren bütün
değişkenlerden görünür.
Her struct, hangi alanlara sahip olursa olsun, kendisini metne dönüştürmek
için iki fonksiyonla gelir. Hata ayıklarken ve başka programların okuyabileceği
çıktı üretirken işe yararlar.
print() yukarıdaki metotlardan ayrı durur: bir tip üzerinde metot değil,
derleyicinin içinde C++ ile yazılmış ve saQut’un FFI katmanı üzerinden
programınıza sunulan bir konuk fonksiyondur (host function). Herhangi bir
tipten tek bir değer alır ve onu yazdırır:
print(42); // 42
print(3.14); // 3.14
print("text"); // text
print(true); // 1 (bool 1 / 0 olarak yazdırılır)
print, FFI seam’i üzerinden açılan ilk host fonksiyondur. Diğer standart
kütüphane fonksiyonları (dosya, matematik vb.) aynı host fonksiyon mekanizmasıyla
açılır.