Thread overview
Bir işlev tasarımının gelişimi
July 03, 2010

Teşekkürler. (Yazıyı okuduğumda ve herşeyi anladıysam yani sadece Teşekkür mesajı yazabiliyorsam o konu hakkında sadece teşekkür mesajı yazayım mı ? Yoksa yazmayım mı ?)
Alıntı:

>

Bu kitabın zaten programcılık bilenlere yönelik olduğunu konuşmuştuk. Zaten bilinen kavramların D'de nasıl oldukları çok hızlı anlatılıyor.

Programcılık bilenlere yönelik derken ne kadar yönelik ? Mesela bir if koşulunu sizin anlattığınız gibi anlatmıyor mu ?

Bu sırada D'yi öğrenirken sanırım ister istemez Aralık ile çalışıyoruz. Erişicilere hiç bulaşmıyoruz ?

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 03, 2010

Şu konuda erişicilerle aralıkları karşılaştırmıştık:

http://ddili.org/forum/thread/330

TDPL'de tam bu konuya değinen bir bölüme rastladım. ("The D Programming Language" kitabına biz de kısaca TDPL diyebiliriz herhalde. :))

Yazar, işlevleri anlatmaya 'find' işlevi ile başlıyor. Kitabın o bölümünü burada özetleyeceğim. (Tabii inatla Türkçe kodla. :D)

Bu kitabın zaten programcılık bilenlere yönelik olduğunu konuşmuştuk. Zaten bilinen kavramların D'de nasıl oldukları çok hızlı anlatılıyor. İşlevlerin tanıtımına işe yarar bir 'find' işleviyle başlıyor ve teker teker tasarımı geliştiriyor.

O şekilde tanıtımı çok akıcı bulduğum için aktarmak istedim. Bunların arasında aralık kavramı da kendisini gösteriyor.

Bir dizide arama yapan bir işlev olsun:

bool ara(int[] dizi, int sayı)
{
   foreach (eleman; dizi) {
       if (sayı == eleman) {
           return true;             // bulundu
       }
   }

   return false;    // bulunamadı
}

void main()
{
   ara([ 10, 1, 42, 5, 7 ], 42);
}

Bulunup bulunmadığını söylemek fazla kullanışlı olmadığı için bulunan elemanın yerini bildirelim. Bulunamazsa yasal olmayan bir indeks döndürür:

int ara(int[] dizi, int sayı)
{
   foreach (i, eleman; dizi) {
       if (sayı == eleman) {
           return i;
       }
   }

   return -1;

}

İndeks kavramı her veri yapısına uygun değildir; örneğin bağlı listenin belirli bir indeksli elemanına gitmek için baştan adım adım ilerlemek gerekeceği için çok yavaş olur.

Onun yerine erişiciler kullanılabilir (gösterge de olur, çünkü o da erişici olarak kullanılabilir). Ama Phobos aralıklara karar verdiği için yazar işte burada aralık kavramına geçiyor.

Erişici yerine, her tür veri yapısı ile çalışabilecek bir başka bir yöntem gösteriyor: Verilen diziyi başından adım adım tüketelim ve bulduğumuz noktadan geri kalanını döndürelim. Hiç bulamazsak, boş dizi dönmüş olur:

int[] ara(int[] dizi, int sayı)
{
   while ((dizi.length > 0) && (dizi[0] != sayı)) {
       dizi = dizi[1 .. $];    // başından tüket
   }

   return dizi;
}

Tabii gerçekten bir "tüketme" olmuyor. Asıl dizi olduğu gibi duruyor. Parametre olarak bir dilim geldiği için, dilimi başından tüketiyoruz. Onun etkisi, dilimi başından daraltmaktır.

Güzel... Ama o işlev kısıtlıdır, çünkü yalnızca int türüyle çalışır. Şablon haline getirerek her türle kullanabiliriz. Şablon yapmak çok kolay: işlev isminden sonra bir '(T)' ekliyoruz ve int'leri T yapıyoruz.

Her tür olabileceği için, artık "sayı" demek uygun olmaz; onu da "değer" yapalım.

int ve double kullanan bir örnek:

T[] ara(T)(T[] dizi, T değer)
{
   while ((dizi.length > 0) && (dizi[0] != değer)) {
       dizi = dizi[1 .. $];
   }

   return dizi;
}

import std.stdio;

void main()
{
   writeln(ara([ 10, 1, 42, 5, 7 ], 42));   // hem int ile
   writeln(ara([ 1.2, 3.4, 5.6 ], 3.4));    // hem de double ile çalışıyor
}

O işlevde yine de bir sorun var: dizi elemanlarının ve aranan değerin aynı türden olmaları gerekiyor. Örneğin double dizide int aramak istesek çalışmaz.

Onun için iki tane şablon parametresi kullanalım:

// E: dizi elemanlarının türü, A: arananın türü
E[] ara(E, A)(E[] dizi, A değer)
{
   while ((dizi.length > 0) && (dizi[0] != değer)) {
       dizi = dizi[1 .. $];
   }

   return dizi;
}

Böylece double dizi içinde int arayabiliriz:

   writeln(ara([ 1.0, 3.0, 5.0 ], 3));

Onun çalışmasının nedeni, işlev içindeki '[dizi[0] != değer' işleminde solda double, sağda int bulunması, ve bunun yasal bir karşılaştırma olmasıdır.

İşlevin bu halindeki sorun da, artık fazla esnek olmasıdır. :) Karşılaştırılamyan türler bile kullanılsa, derleyici izin verir:

   writeln(ara([ 1.0, 3.0, 5.0 ], "merhaba"));

Evet, bir derleme hatası olur; ama o hata, işlevin uyumsuz parametrelerle çağrıldığı yukarıdaki satıra değil, işlevin içindeki '[dizi[0] != değer' karşılaştırmasına işaret eder. İyi değil! :) Amaç, derleme hatasının uyumsuz türlerin kullanıldığı "merhaba"lı satıra işaret etmesidir.

O zaman şablon kısıtlaması (template constraint) tanımlarız:

E[] ara(E, A)(E[] dizi, A değer)
   if (is (typeof(dizi[0] != değer) : bool))
{
   while ((dizi.length > 0) && (dizi[0] != değer)) {
       dizi = dizi[1 .. $];
   }

   return dizi;
}

Ne yazık ki çok karışık... :/ Oradaki şablon kısıtlaması, o şablonun ancak '[dizi[0] != değer' karşılaştırmasının sonucunun 'bool' olduğu durumlarda göze alınacağını söyler. Bir anlamda, "bu şablonun çalışabilmesi için bu koşulun gerçekleşmesi gerekir" der.

Yasal olmayan karşılaştırmaların sonucunda 'is' ifadesi 'void' bile olmayan "türsüzlük" üretir ve o da 'bool'a eşit olmaz.

Yukarıdaki kullanımda derleme hatası, artık "merhaba"lı satıra işaret eder.

Bu noktada bir de isimli şablon kısıtlaması tanımlayabiliriz. (Bu adım kitapta yok). Öyle yapınca, şablon kısıtlamasına okunaklı bir isim verilmiş olur:

E[] ara(E, A)(E[] dizi, A değer)
   if (karşılaştırılabilir_mi!(E, A))
{
   while ((dizi.length > 0) && (dizi[0] != değer)) {
       dizi = dizi[1 .. $];    // başından tüket
   }

   return dizi;
}

O isimli kısıtlama şöyle tanımlanabilir:

template karşılaştırılabilir_mi(A, B)
{
   const bool karşılaştırılabilir_mi = is (typeof(A.init != B.init) : bool);
}

Tabii bu işlevin birim testinin de en başından beri yazılmış olması gerekiyordu. :) O da şöyle bir şey olabilir:

unittest
{
   // İlk bulunduğu noktadan gerisini vermeli
   assert(ara([ 10, 1, 42, 5, 7, 42 ], 42) == [ 42, 5, 7, 42 ]);

   // Bulunamazsa boş dizi dönmeli
   assert(ara([ 10, 1 ], 42) == []);

   // double dizide int aranabilmeli
   assert(ara([ 1.0, 3.0, 5.0 ], 3) == [ 3.0, 5.0 ]);
}

Dinlediğiniz için teşekkürler... :)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

July 03, 2010

Alıntı (canalpay):

>

konu hakkında sadece teşekkür mesajı

Bence yazmaya gerek yok ve kendim hiç aramıyorum.

Forumlara ilk takıldığımda bu konuda daha katıydım; acaba ben de şimdi "rica ederim, ne önemi var mı" demeliyim diye düşünürdüm. :) Ama sonradan katılığım geçti. Kendim hiç beklemiyorum ama teşekkürü vermek isteyene de bir şey diyemeyiz tabii...

Daha doğrusu, ben beklemiyor değil, nasıl olsa birisinin işine yarıyordur ve memnun olunuyordur diye düşünüyorum.

Alıntı:

>

Alıntı:

>

Bu kitabın zaten programcılık bilenlere yönelik olduğunu konuşmuştuk. Zaten bilinen kavramların D'de nasıl oldukları çok hızlı anlatılıyor.

Programcılık bilenlere yönelik derken ne kadar yönelik ? Mesela bir if koşulunu sizin anlattığınız gibi anlatmıyor mu ?

Hayır, hic benim anlattığım gibi değil. Çok hızlı başlayan ilk bölümü internette vardı. O bölüm genel olarak tanıtmak içindi.

Ondan sonraki bölümün başlığı "Temel Türler ve İfadeler". Bütün ifadeler madde madde tanıtılıyorlar. Ondan sonraki bölüm, "Deyimler"... Yine, teker teker tanıtılıyorlar. O şekilde ancak bir referans kitabı olabilir. Zaten başka bir şey olduğu da iddia edilmiyor.

while deyiminin anlatıldığı bölümü çevireyim:

Alıntı (TDPL):

>

3.7 Döngü deyimleri

(Burada döngü kavramının ne olduğu ile ilgili hiçbir açıklama yok. Programlama bilen kimseye açıklayacak bir şey de yoktur zaten.)

3.7.1 while deyimi

Evet, doğru bildiniz:

> while (<ifade>) <deyim>
> ```

>
> İşlem, <ifade>yi işleterek başlar. Eğer sıfır değilse, <deyim> işletilir ve döngü, tekrar <ifade>nin işletilmesine geçer. Değilse, 'while' deyiminin işi bitmiştir; bir sonraki deyime geçilir.
>

Hepsi o... Yani söylemek istediğim de o. :) Zaten programlama bilen kişiye 'while''ı başka ne kadar anlatabiliriz? TDPL öyle bir kitap.

Ama içinde güzel fikirler ve dilin tasarımı konuları da geçiyor. Ama o konular da ileri derece konular.

Örneğin işlevler bölümünde, yalnızca referans türlerini seçen Java gibi dillerdeki "homogeneous translation" ve C++ gibi şablonlu dillerdeki "heterogeneous translation" kavramlarına giriyor. Bunlar dil ve derleyici teknolojilerine ait kavramlar. :) Deneyimli programcıların günlük hayatlarında bile yerleri yoktur.

Özet: TDPL, programcılığa yeni yeni başlayanlara göre değil ama zaten programcılık bilenleri de sıkmaz. Yukarıdaki while bölümü zaten her dilde aynıdır ve o kadarı yeter.

Alıntı:
> Bu sırada D'yi öğrenirken sanırım ister istemez Aralık ile çalışıyoruz. Erişicilere hiç bulaşmıyoruz ?

Doğru. Erişici eski teknoloji, yaşasın aralıklaaar! :-p

Ama aralıklar da o kadar yeni ki, bütün bilgisayar camiası kabul etmiş değil. Şüphe duyanlar da var. Haklılar da, bugüne kadar erişiciler yetmiş işte diye düşünülebilir.

Ali

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]