D.ershane D Programlama Dili
Ali Çehreli

çokuzlu: [tuple], bir kaç parçanın diziye benzer şekilde bir araya gelmesinden oluşan yapı
iç olanak: [core feature], dilin kütüphane gerektirmeyen bir olanağı
Phobos: [Phobos], D dilinin standart kütüphanesi
... bütün sözlük

Bölümler
İngilizce Kaynaklar
Diğer



Çokuzlular

Çokuzlu, birden fazla değişkeni bir araya getiren ve bir yapı nesnesi gibi kullanılmalarını sağlayan olanaktır. Bazı dillerin iç olanağı olan çokuzlular D'de std.typecons.Tuple ile bir kütüphane olanağı olarak gerçekleştirilmiştir.

Çokuzlular çoğunlukla kolaylık işlevi olan tuple() ile oluşturulurlar:

import std.stdio;
import std.typecons;

void main()
{
    auto çokuzlu = tuple(42, "merhaba");
    writeln(çokuzlu);
}

Yukarıdaki tuple() işlevi, 42 değerindeki int'in ve "merhaba" değerindeki string'in bir araya gelmesinden oluşan bir nesne oluşturur. Bu nesnenin türünü ve üyelerinin değerlerini programın çıktısında görüyoruz:

Tuple!(int,string)(42, merhaba)

O nesnenin aşağıdaki sözde yapı gibi gerçekleştirilmiş olduğunu düşünebilirsiniz:

// Tuple!(int, string)'in eşdeğeri
struct __Çokuzlu_int_string
{
    int __üye_0;
    string __üye_1;
}

Çokuzluların üyelerine normalde sıra numarasıyla erişilir. Bu açıdan bakıldığında her bir elemanı farklı türden olabilen küçük bir dizi gibi düşünebiliriz:

    writeln(çokuzlu[0]);
    writeln(çokuzlu[1]);

Çıktısı:

42
merhaba

Çokuzluların üyelerine sıra numarasıyla erişilmesi başka dillerde de yaygındır. Phobos çokuzlularının üyelerine ise nitelik isimleriyle de erişilebilir. Bu, tuple() işlevi çağrılarak sağlanamaz; Tuple şablonunun açıkça yazılması gerekir. Üyelerin türleri ve nitelik isimleri çiftler halinde belirtilirler:

    auto çokuzlu = Tuple!(int, "sayı",
                          string, "mesaj")(42, "merhaba");

Yukarıdaki tanım, int türündeki sıfırıncı elemana ayrıca .sayı niteliğiyle ve string türündeki birinci elemana ayrıca .mesaj niteliğiyle erişilmesini sağlar:

    writeln("0 sıra numarasıyla    : ", çokuzlu[0]);
    writeln(".sayı niteliği olarak : ", çokuzlu.sayı);
    writeln("1 sıra numarasıyla    : ", çokuzlu[1]);
    writeln(".mesaj niteliği olarak: ", çokuzlu.mesaj);

Çıktısı:

0 sıra numarasıyla    : 42
.sayı niteliği olarak : 42
1 sıra numarasıyla    : merhaba
.mesaj niteliği olarak: merhaba
Ne zaman kullanmalı

Aynı amaç için yapılar da kullanılabildiğinden çokuzlular şart değildir. Öte yandan, tür tanımlamak gerekmeden nesne oluşturabildiklerinden kullanımları daha kolaydır.

Çokuzlular, işlevlerin tek değer döndürebilme yetersizliklerine karşı basit bir çözüm olarak görülebilirler. Örneğin std.algorithm.findSplit, bir aralığı başka bir aralık içinde arar ve arama sonucunda üç bilgi üretir. Bu bilgiler; bulunan aralıktan öncesini, bulunan aralığı, ve bulunan aralıktan sonrasını belirtirler. findSplit(), bu üç parça bilgiyi bir çokuzlu olarak döndürür:

    auto bütünAralık = "merhaba";
    auto aranan = "er";

    auto sonuç = findSplit(bütünAralık, aranan);

    writeln("öncesi : ", sonuç[0]);
    writeln("bulunan: ", sonuç[1]);
    writeln("sonrası: ", sonuç[2]);

Çıktısı:

öncesi : m
bulunan: er
sonrası: haba

Bulunamadığı durumda sıfırıncı parça bütün aralığı içerir; diğerleri boştur:

    auto sonuç = findSplit("merhaba", "yer");

    writeln("öncesi : ", sonuç[0]);
    writeln("bulunan: ", sonuç[1]);
    writeln("sonrası: ", sonuç[2]);

Aranan "yer" asıl aralıkta bulunmadığı için son ikisi boştur:

öncesi : merhaba
bulunan: 
sonrası: 

Kendi programlarınızda kullanacağınız çokuzlu üyelerinin findSplit()'tekiler kadar yakın kavramlar olmalarını gözetmenizi öneririm. Yoksa yapı nesneleri döndürmek daha uygun olabilir.

Tür çokuzluları

D'nin çok üst düzey bir olanağı, tür çokuzlularıdır. Tür çokuzluları, derleyiciden de destek alınarak tanımlanmış olan std.typetuple.TypeTuple ile gerçekleştirilmiştir.

TypeTuple'un özelliği, üyelerinin belirli türlerden nesneler değil, belirli türlerin kendileri olmalarıdır. Örneğin TypeTuple!(int, string) çokuzlusunun üyeleri, int türü ve string türüdür. Bu türlere foreach döngüsü içinde teker teker erişilebilir.

Çoğunlukla birim testlerinde ve aynı testin birden fazla tür için tekrarlanmasının gerektiği durumlarda yararlıdır. Örneğin findSplit() algoritmasının string, wstring, ve dstring türlerinin hepsiyle de doğru çalıştığını denetleyen bir birim testi aşağıdaki gibi yazılabilir:

unittest
{
    foreach (Tür; TypeTuple!(string, wstring, dstring)) {
        Tür bütünAralık = "abcçdefgğ";
        Tür aranan = "çd";

        auto sonuç = findSplit(bütünAralık, aranan);

        Tür beklenen_öncesi = "abc";
        Tür beklenen_bulunan = "çd";
        Tür beklenen_sonrası = "efgğ";

        assert(sonuç[0] == beklenen_öncesi);
        assert(sonuç[1] == beklenen_bulunan);
        assert(sonuç[2] == beklenen_sonrası);
    }
}

Döngü değişkeni olan Tür, foreach döngüsünün her ilerletilişinde TypeTuple'un içerdiği türlerden birisi haline gelir.

Özet