Forum: D Programlama Dili RSS
Dinamik dizilerin "yarım referans" tarafları
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Dinamik dizilerin "yarım referans" tarafları
Bu konuyu daha önce de çok konuştukmuştuk: D'nin dinamik dizileri başka dillerdekilere benzemiyor. d.D grubunda "Passing dynamic arrays" diye bir konu açılınca hatırlamak için bir program daha yazdım.

Aşağıdaki programda "dinamik dizi" yerine "dilim" diyorum çünkü aslında ikisi de aynı şey: kendilerine ait elemanları bulunmayan, yalnızca o elemanlara erişim sağlayan olanaklar.

D'nin dilimlerinin garip tarafı, aynı elemanlara erişim sağlayan birden fazla dilim bulunduğunda ortaya çıkabiliyor: dilimlerden birisinin uzunluğu arttığında artık aynı elemanlara erişim sağlamaz hale geliyorlar. Uzunluk artınca elemanlar kopyalanıyor ve uzunluğu artan dilim bu yeni elemanlara erişim sağlamaya başlıyor. Dilimler o zamana kadar aynı elemanlara erişim sağlıyorlarken, uzunluğun artmasından sonra artık farklı elemanlara erişim sağlıyorlar.

Programı -unittest seçeneği ile derlemek gerekiyor...

void uzunluğunu_değiştirmeden(int[] dilim)
{
    /*
     * 'dilim', işleve gönderilen dilimle aynı elemanlara erişim
     * sağlamaktadır. Elemanlarda burada yapılan değişiklikler asıl dizideki
     * elemanları da etkiler.
     */
    dilim[0] = 0;
    dilim[1] = 1;
 
    assert(dilim == [ 0, 1, 9 ]);
}
 
unittest
{
    int[] d =       [ 9, 9, 9 ];
    uzunluğunu_değiştirmeden(d);
    assert(d ==     [ 0, 1, 9 ]);
}
 
void uzat(int[] dilim)
{
    /*
     * Dilimin uzunluğu artana kadar asıl elemanlara erişim sağlanmaktadır; bu
     * değişiklik, asıl dizinin elemanını da değiştirir
     */
    dilim[0] = 0;
 
    /*
     * 'dilim'in uzunluğunun arttırılması; onun artık asıl elemanlara değil, o
     * elemanların kopyalarına erişim sağlamasına neden olur.
     */
    ++dilim.length// <-- Bu işlem sonucunda bütün elemanlar KOPYALANIRLAR
 
    /* O yüzden bu; artık asıl diziyi değil, yalnızca bu yerel dilimi
     * etkiler */
    dilim[1] = 1;
 
    /* Asıl dizide bulunmayan bir elemanı değiştiriyoruz */
    dilim[3] = 3;
 
    assert(dilim == [ 0, 1, 9, 3 ]);
}
 
unittest
{
    int[] d =       [ 9, 9, 9 ];
    uzat(d);
    assert(d ==     [ 0, 9, 9 ]);
}
 
void eleman_ekle(int[] dilim)
{
    /*
     * Bu da uzat() işlevindeki gibidir; eleman eklenene kadar asıl dizideki
     * elemanlar; eklendikten sonra ise yerel kopyalar değişir
     */
 
    dilim[0] = 0;
 
    dilim ~= 3// <-- Bu işlem sonucunda bütün elemanlar KOPYALANIRLAR
 
    dilim[1] = 1;
 
    assert(dilim == [ 0, 1, 9, 3 ]);
}
 
unittest
{
    int[] d =       [ 9, 9, 9 ];
    eleman_ekle(d);
    assert(d ==     [ 0, 9, 9 ]);
}
 
void kısalt(int[] dilim)
{
    /*
     * Diğer işlevlerde olduğu gibi, şimdilik asıl dizideki elemanı değiştirir
     */
    dilim[0] = 0;
 
    /*
     * 'dilim'in uzunluğunda yapılan değişiklik, onun daha az sayıda elemana
     * erişim sağlamasına neden olur. Ama hâlâ asıl dilimdeki elemanlara
     * erişim sağlamaktadır.
     */
    --dilim.length;
 
    /* O yüzden bu, asıl diziyi de etkiler */
    dilim[1] = 1;
 
    assert(dilim == [ 0, 1 ]);
}
 
unittest
{
    int[] d =       [ 9, 9, 9 ];
    kısalt(d);
    assert(d ==     [ 0, 1, 9 ]);
}
 
void ref_parametre_olarak(ref int[] dilim)
{
    /* Parametre listesinde 'ref' olarak belirtildiği için, bu işlevdeki
     * 'dilim', asıl dizinin takma ismi gibi işlemektedir. Burada yapılan
     * değişiklikler doğrudan asıl diziyi etkiler. */
    dilim[0] = 0;
    ++dilim.length;
    dilim[1] = 1;
    dilim[3] = 3;
    dilim ~= 4;
 
    assert(dilim == [ 0, 1, 9, 3, 4 ]);
}
 
unittest
{
    int[] d =       [ 9, 9, 9 ];
    ref_parametre_olarak(d);
    assert(d ==     [ 0, 1, 9, 3, 4 ]);
}
 
void main()
{}

Akılda tutmakta yarar var. :)

Ali
acehreli (Moderatör) #2
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Sabit uzunluklu dizilerde böyle bir gariplik yok; çünkü onların uzunlukları değiştirilemiyor.

Ayrıca, C ailesinden gelen dillerin tersine, sabit uzunluklu diziler D'de işlevlere normalde kopyalanarak geçiriliyorlar. Açıkça ref yazınca referans olarak geçiriliyorlar.

void sabit_uzunluklu_dizi(int[3] dizi)
{
    /*
     * Sabit uzunluklu diziler işlevlere normalde kopyalanırlar. O yüzden,
     * burada yapılan değişiklikler yalnızca yerel diziyi etkiler.
     */
    dizi[0] = 0;
 
    /*
     * Uzunluğu zaten değiştirilemez; bunların hepsi derleme hatasıdır
     *
     * ++dizi.length;
     * --dizi.length;
     * dizi ~= 3;
     */
 
    assert(dizi == [ 0, 9, 9 ]);
}
 
unittest
{
    int[3] d =     [ 9, 9, 9 ];
    sabit_uzunluklu_dizi(d);
    assert(d ==    [ 9, 9, 9 ]);
}
 
void ref_parametre_olarak_sabit_uzunluklu_dizi(ref int[3] dizi)
{
    /* Parametre ref olarak bildirildiği için, buradaki 'dizi', asıl dizinin
     * takma ismi gibi işler. */
    dizi[0] = 0;
 
    assert(dizi == [ 0, 9, 9 ]);
}
 
unittest
{
    int[3] d =     [ 9, 9, 9 ];
    ref_parametre_olarak_sabit_uzunluklu_dizi(d);
    assert(d ==    [ 0, 9, 9 ]);
}
 
void main()
{}

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-23, 23:24:20 (UTC -08:00)