November 18, 2010

immutable ve const konusunda yazılar okuduk ve biraz olsun konuştuk. Böyle bir ayrım bulunmayan C++ dilinden geldiğim için ben hâlâ ikisinden nasıl yararlanılacağından tam olarak emin değil(d)im.

immutable, hiçbir şekilde değişmez demek. const ise bu isimle (veya burada) kullanıldığında değişmez demek.

Şu kadarından eminim: İşlev parametrelerini 'immutable' yapmak, belki de gereksiz olan bir kısıtlama getiriyor: işlevin kullanımını yalnızca 'immutable' nesneler ile kısıtlıyor.

Not: Eğer bu programları denemek isterseniz, dmd'ye -unittest seçeneğini de verin:

'dmd deneme.d -ofdeneme -w -unittest
/deneme'

Aşağıdaki gücü_yeter_mi, parametresini önerilen şekilde const olarak alıyor:

class Robot
{
   this(int güç)
   {
       güç_ = güç;
   }

   @property int güç() const
   {
       return güç_;
   }

private:

   int güç_;
}

int gücü_yeter_mi(const Robot robot, int gereken_güç)
{
   return robot.güç >= gereken_güç;
}

unittest
{
   auto r = new Robot(42);

   assert( gücü_yeter_mi(r, 41));
   assert( gücü_yeter_mi(r, 42));
   assert(!gücü_yeter_mi(r, 43));
}

void main()
{}

gücü_yeter_mi, kullandığı Robot'ta bir değişiklik yapmayacağı için o parametreyi const olarak belirlemiş. Orada const yerine immutable kullanmak, gereksizce "bana vereceğiniz parametre kesinlikle değiştirelemeyen bir nesne olsun" diye diretmek anlamına gelirdi:

int gücü_yeter_mi(immutable Robot robot, int gereken_güç)
// ...
   assert( gücü_yeter_mi(r, 41));  // <--- HATA

Derleme hatası:

'Error: function deneme.gücü_yeter_mi (immutable immutable(Robot) robot, int gereken_güç) is not callable using argument types (Robot,int)
Error: cannot implicitly convert expression (r) of type deneme.Robot to immutable(Robot)
'

Ayrıca, 'immutable' olarak işaretlenmiş değişkenlerin eş zamanlı çalışma (multithreaded, concurrent) konusunda kolaylık ve hız kazancı getirdiklerini biliyorum: Hiçbir zaman değişmeyecekleri için bu tür değişkenlere erişimin mutex vs. yoluyla denetlenmeleri gerekmiyor; çünkü derleyici onların değiştirilmelerine zaten izin vermiyor.

Bu uzun girişten sonra, bu yazıyı yazma nedenime geldim. :) İyi D'cilerden olan Jonathan M Davis de C++'dan gelen birisi. immutable veya const kullanımını yerel değişkenler için sormuş; çünkü yerel değişkenler için const veya immutable kullanmak farketmiyor.

Yanıt verenler yerel değişkenleri olabildiğince immutable yaptıklarını ve bu ilkeden memnun olduklarını söylüyorlar.

Yerel değişkenleri immutable tanımlamak, gereksizce kısıtlı tasarlanmış olan işlevleri de kullanabilmeyi sağlayabiliyor. Yukarıdaki gücü_yeter_mi işlevi gerekmese de immutable parametre alsa, onu çağırabilmenin bir yolu, eğer olabiliyorsa, yerel r'yi immutable tanımlamak olurdu. Bu durumda program derlenirdi:

// Gereksizce immutable Robot istiyor
int gücü_yeter_mi(immutable Robot robot, int gereken_güç)
// ...
   immutable r = new immutable(Robot)(42);

(Not: O yazımın doğrusunu bulmak biraz zor oldu. :) Yalnızca auto'yu immutable'a çevirmek yetmedi, çünkü derleyici sağ taraftaki değişebilen nesneyi soldaki immutable referansa atamaya izin vermedi.)

Özet:

  • Yeni ilke: Yerel değişkenler olabildiğince immutable olmalı

  • Zaten bildiğim ilke: Eğer geçerli bir nedeni yoksa, işlev parametreleri const olmalı

Aslında bunu "referans olan işlev parametreleri" diye düzeltmek gerek: sınıf, dizi, eşleme tablosu, ref türünde parametreler, başka?, vs. Çünkü referans olmayan parametreler zaten kopyalanarak geçirildikleri için, onları immutable tanımlamak, yalnızca işlevin kendisini etkiliyor.

Ali

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