Yukarıdaki “yerel kopya” kuralı ilkel tipler için geçerlidir. Bileşik
tipler (struct, dizi, string) referans ile aktarılır: fonksiyon
aynı alt veriyi alır, dolayısıyla yaptığı değişiklikler çağıran tarafından
görülür:
voidfill(int[]a) {
a[0] =99; // çağıranın dizisini değiştirir
}
intmain() {
int[] x = [1, 2, 3];
fill(x);
print(x[0]); // 99, değişiklik kalıcı oldu
return0;
}
Aynı durum struct’lar için de geçerlidir: bir alanı değiştiren fonksiyon,
çağıranın struct’ını da değiştirir. (Bkz. referans anlamsallığı.)
Bu verimlidir (kopyalama yoktur) ancak bir fonksiyonun kendisine
aktarılanı değiştirebileceği anlamına gelir. Bunu istemiyorsanız,
fonksiyon parametresine yazmaktan kaçınmalıdır.
Bir fonksiyon bir struct döndürdüğünde, çağıran dönen değere bir referans
alır:
struct Point { int x; int y; }
Point origin() {
Point p;
p.x=0;
p.y=0;
return p;
}
Kısıtlama: dizi dönüş tipleri desteklenmez. Şu anda
int[] makeList() { ... } yazamazsınız: dizi dönüş tipi ayrıştırılamaz.
Geçici çözüm, diziyi bir struct içine sarıp onu döndürmektir:
struct IntList { int[] items; }
IntList range() {
IntList r;
r.items= [1, 2, 3];
return r;
}
Alternatif olarak, diziyi bir referans parametresi olarak alıp yerinde
doldurabilirsiniz (yukarıdaki fill örneğine bakın).
Aşırı yükleme (overloading) yok. Bir fonksiyon adı tek bir fonksiyona
işaret eder; aynı isimle farklı parametrelere sahip iki fonksiyon
tanımlayamazsınız.
Varsayılan parametre değeri yok. Her parametre açıkça belirtilmelidir;
argüman sayısı eşleşmelidir (aksi halde E008
alırsınız).
İç içe fonksiyon yok. Fonksiyonlar en üst düzeyde tanımlanır, asla
başka bir fonksiyonun gövdesi içinde tanımlanamaz (bu E011
hatasıdır).
Derin özyineleme çağrı yığınını kullanır. Her çağrı bir çerçeve ekler;
aşırı derin özyineleme yığını tüketebilir, bu yüzden çok büyük girdiler
için yinelemeli (iterative) bir sürümü tercih edin.