Jump to page: 1 2
Thread overview
out bloğu in bloğunu göremez
Jul 02, 2012
zafer
Jul 02, 2012
zafer
Jul 03, 2012
Kadir Can
Jul 03, 2012
Salih Dinçer
Jul 03, 2012
Salih Dinçer
Jul 03, 2012
Salih Dinçer
Jul 04, 2012
Salih Dinçer
December 07, 2010

D'nin sözleşmeli programlama olanaklarında bir eksiklik var: 'out' bloğu içindeyken 'in' bloğu içindeki değişkenlere erişilemiyor. (1)

Aslında bunun temel nedeni, farklı blokların birbirlerini görememeleridir:

   {
       int i = 42;
   }

   {
       int j = i; // derleme hatası: 'i' tanımlı değil!
   }

Bu durum in ve out blokları için de geçerlidir; ama ne yazık ki o durumda bir eksiklik olarak görülebiliyor. Çünkü bazen belirli bir durumun değişmediğini denetlemek isteyebiliriz. Örneğin bazı sınıf üyeleri eski değerlerini korumalıdırlar. D haber grubunda bununla ilgili bir konu açıldı; oradan uyarlıyorum.

Elimizde şöyle bir program olsun:

struct Nokta
{
   int satır;
   int sütun;
}

struct DörtgenBölge
{
   Nokta solÜst;
   int en;
   int boy;

   this(Nokta solÜst, int en, int boy)
   {
       this.solÜst = solÜst;
       this.en = en;
       this.boy = boy;
   }

   /**
    * Bölgenin yerini değiştirir
    *
    * Params:
    *    yukarı = yukarı öteleme miktarı; eksi değer aşağı öteler
    *    sağa = sağa öteleme miktarı; eksi değer aşağı öteler
    */
   void ötele(int yukarı, int sağa)
   {
       solÜst.satır += yukarı;
       solÜst.sütun += sağa;
   }
}

void main()
{
   auto bölge = DörtgenBölge(Nokta(-1, -2), 30, 40);
   bölge.ötele(5, 6);
}

Oradaki 'ötele' işlevi sırasında dörtgenin eninin veya boyunun değişmemesini isteriz. Yani amaç, ötele'nin bunları değiştirmediğini denetlemek. (Not: Bu sınıf farklı şekillerde de tasarlanabilir. Saçma geliyorsa göz yumun lütfen. :))

Akla ilk gelen ve çalışması gereken çözüm, in ve out bloklarıdır:

   void ötele(int yukarı, int sağa)
   in
   {
       // Eski değerleri hatırlayalım ...
       immutable int eskiEn = en;
       immutable int eskiBoy = boy;
   }
   out
   {
       // ... ve karşılaştıralım
       assert(en == eskiEn);
       assert(boy == eskiBoy);
   }
   body
   {
       solÜst.satır += yukarı;
       solÜst.sütun += sağa;
   }

İşte, out bloğu in bloğunun içini göremediği için derleme hatası alırız:

'
Error: undefined identifier eskiEn
Error: undefined identifier eskiBoy
'

(Not: Daha önceden konuştuğumuz gibi, değişmeyeceğini bildiğim yerel değişkenleri de 'immutable' olarak işaretledim.)

Bunun en güzel çözümü, out bloklarının bir istisna olarak in bloklarını görebilmeleri olurmuş; ama dmd'yi bu şekilde değiştirmek çok dertli olduğu için şimdilik ertelemişler.

Bir başka öneri, dile 'old' diye bir anahtar sözcük eklemek ve eski değişkenlerin otomatik olarak saklanmalarını sağlamakmış. Bu durumda in bloğuna da gerek kalmadan:

   void ötele(int yukarı, int sağa)
   out
   {
       assert(en == old.end);
       assert(boy == old.boy);
   }
   body
   {
       solÜst.satır += yukarı;
       solÜst.sütun += sağa;
   }

Ama öyle bir olanak da henüz yok. :/

Andrei Alexandrescu'nun önerdiği çözüm, bu yetersizliği kabul etmek ve böyle durumlarda da 'scope''tan yararlanmak: (2)

   void ötele(int yukarı, int sağa)
   {
       debug {
           immutable int eskiEn = en;
           immutable int eskiBoy = boy;

           scope (exit) {
               assert(en == eskiEn);
               assert(boy == eskiBoy);
           }
       }

       ++en; // İstenmeyen bir değişiklik; bunu yakalayacağız

       solÜst.satır += yukarı;
       solÜst.sütun += sağa;
   }

Bütün denetimi de bir 'debug' bloğu içine alıyor... Böylece yalnızca özellikle '-debug' seçeneği kullanıldığında etkilidirler. (Garip bir şekilde, '-debug' ile '-release' birbirlerinin tersi değildir.)

O konuda yeni bir şey daha öğrendim: 'else', 'debug' blokları ile de kullanılabiliyormuş:

   debug {
       // ... -debug seçeneği kullanılmışsa ...

   } else {
       // ... kullanılmamışsa ...
   }

'else''i aslında Koşullu Derleme dersinde 'version' ile kullanmışız, ve version ile debug kardeş olanaklar... (3)

Yukarıdaki konular şu sayfalarda geçiyor:

(1) Sözleşmeli Programlama

http://ddili.org/ders/d/sozlesmeli.html

(2) Hata Atma ve Yakalama

http://ddili.org/ders/d/hatalar.html

(3) Koşullu Derleme

http://ddili.org/ders/d/kosullu_derleme.html

Ali

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

July 02, 2012

Bende sözleşmeli programlama dersini okuyordum ve bu aklıma gelmişti: https://github.com/acehreli/pisti/blob/master/pisti/g%C3%B6revli.d#L15 (otomatik gitmezse 15.satıra gidiniz.) Sorusunu eski bölümlerden hangisine sorayım diye arama yaparken bu başlığı tekrar görmüş oldum. Bana andreinin çözümü oldukça iyi geldi. Yapamadım ancak global değişken kullansak olmaz mı? immutable olursa global kullanmanın kötü bir yanıda kalmazdı sanki?

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

July 02, 2012

Sanırım sözleşmeli programlama ile hala mesafeli olduğum için Andrei Alexandrescu'nun çözümü banada daha yakın geldi. Mesajında aklıma takılanlar ise şunlar;

Alıntı (acehreli):

>

Garip bir şekilde, -debug ile -release birbirlerinin tersi değildir.

Burada ne demek istediğini tam olarak anlamadım Ali, biraz daha açabilir misin?

Alıntı (acehreli):

>

O konuda yeni bir şey daha öğrendim: else, debug blokları ile de kullanılabiliyormuş:

debug {
    // ... -debug seçeneği kullanılmışsa ...

} else {
    // ... kullanılmamışsa ...
}

Burada else tam olarak ne işe yarıyor anlamadım. Yani -debug kullanılmışsa zaten debug bloğu çalışacak aksi takdirde program normal akışına devam edecek. Nasıl bir durumda böyle bir yapıya ihtiyaç duyarız ?

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

July 03, 2012

Ali doğruyu söylemek gerekirse bu konuyu hala tam olarak anlamış değilim, belki ileryen zamanda kodlar içinde kullandıkça yerine oturur.

import std.stdio;

void main()
{
   debug
   {
       writeln("Bu kodlar -debug modunda calisir.");
   }
   else
   {
       writeln("Burasi else olarak calisir.");
       writeln("Normal program ciktisi");
   }

   writeln("Burasi her zaman calisir.");
}

Diğer taraftan örnek kodda görüldüğü gibi belki daha temiz bir debug çıktısı için kullanılabilir. Burada programın normal çıktısı else bloğuna alınarak debug işletiminde ekran çıktısının daha temiz olması sağlanıyor. Böylece hata ayıklama süreci daha rahat olabilir.

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

July 03, 2012

Senin yönteminde eğer en üyesi yasal bir şekilde değiştirilirse sıkıntı olur.Mesela iki dörtgensel bölgeyi yan yana koyup yeni bir bölge oluşturan ilev yazarsak yanlış çalışır.
Ayrıca yapının boyutu büyür.
Andrei parametreleri işleve girmeden önce depolaması gerektiği için ve out, in bloğundaki yerel değişkenleri göremediği için değişkenleri işleve girilmeden önce debug içinde depolamış ve çıkışta kontrol etmek için scope(exit) kullanmış.

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

July 03, 2012

Şöyle bir şey de olmaz mı?

struct Nokta
{
   int satır;
   int sütun;
}
import std.conv;
struct DörtgenBölge
{
   Nokta solÜst;
   int en;
   int boy;
immutable int eskiEn;immutable int eskiBoy;
   this(Nokta solÜst, int en, int boy)
   {
       this.solÜst = solÜst;
       this.en = en;
       this.boy = boy;eskiEn = to!(immutable int)(en);eskiBoy = to!(immutable int)(boy);
   }

   /**
    * Bölgenin yerini değiştirir
    *
    * Params:
    *    yukarı = yukarı öteleme miktarı; eksi değer aşağı öteler
    *    sağa = sağa öteleme miktarı; eksi değer aşağı öteler
    */
    void ötele(int yukarı, int sağa)

   out
   {
       // ... ve karşılaştıralım
       assert(en == eskiEn);
       assert(boy == eskiBoy);
   }
   body
   {
       solÜst.satır += yukarı;
       solÜst.sütun += sağa;
   }
}

void main()
{
   auto bölge = DörtgenBölge(Nokta(-1, -2), 30, 40);
   bölge.ötele(5, 6);
}

Andrei out yerine niye scope(exit) kullanmış?

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

July 03, 2012

Alıntı (zafer):

>

Alıntı (acehreli):

>

Garip bir şekilde, -debug ile -release birbirlerinin tersi değildir.

Burada ne demek istediğini tam olarak anlamadım Ali, biraz daha açabilir misin?

debug blokları program -debug seçeneği ile derlendiğinde etkinleşir, değilse etkinleşmez. Onların else'leri de vardır ve ters anlamda etkilidirler: -debug kullanılmamışsa etkilidirler.

else'i şurada version ile kullanmışım ama debug ile kullanmamışım:

http://ddili.org/ders/d/kosullu_derleme.html

Ama olsun, debug için de geçerlidir ve zaten version ve debug perde arkasında hemen hemen aynı biçimde gerçekleştirilmişlerdir.

Ali

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

July 03, 2012

Alıntı (acehreli:1291748274):

>

Bir başka öneri, dile 'old' diye bir anahtar sözcük eklemek ve eski değişkenlerin otomatik olarak saklanmalarını sağlamakmış. Bu durumda in bloğuna da gerek kalmadan:

>     void ötele(int yukarı, int sağa)
>     out
>     {
>         assert(en == old.end);
>         assert(boy == old.boy);
>     }
>     body
>     {
>         solÜst.satır += yukarı;
>         solÜst.sütun += sağa;
>     }
> ```

> Ama öyle bir olanak da henüz yok. :/
>
Peki öyle bir olanağa gerek var mı? Bence aşağıdaki yapıyı "nested struct" şeklinde ve 'ötele()' işlevi üstüne yerleştirmek sorunu çözecektir.

struct eskisi {
int en, boy;
} eskisi old;


Tabi bence, yine **'in'** kümesini kullanmalıyız. Böylece bahsedilen old olanağı varmış gibi kullanılabilir; ya da farklı bir şekilde de olabilir...

void ötele(int yukarı, int sağa)
in
{
// Eski değerleri hatırlayalım ...
old.en = en;
old.boy = boy;
}
out
{
// ... ve karşılaştıralım
assert(en == old.en);
assert(boy == old.boy);
}
body
{
//old.en = 0;
solÜst.satır += yukarı;
solÜst.sütun += sağa;
}



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

Aslında bu örnekte bölge ismiyle gerektiği kadar (her yapıya bir tane) eski koordinat tutulmakta:

void main()
{
   auto bölge = DörtgenBölge(Nokta(-1, -2), 30, 40);
   bölge.ötele(5, 6);
}

Şimdi burada soru DörtgenBölge yapısının elemanları public olmamalı mı? Olmaz ise zaten başka bir işlev tarafından değişmeyeceği için sorun da olmayacaktır. Sonuçta bu örneğe basit ve kısa bir çözüm. Örneği değiştirirsek çözümleri de değiştirebiliriz veya yapıyı farklı şekilde yapabiliriz.

Ayrıca 'in' ile 'out' kümesi arasındaki iletişimi legal olarak sağlamış olduk...

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

July 03, 2012

Alıntı (zafer):

>

hala tam olarak anlamış değilim, belki ileryen zamanda kodlar içinde kullandıkça yerine oturur.

Bir kere bile kullanacağını düşünsem sana katılırım. :) debug neyse ama debug'ın else'i herhalde hiçbir programcının hiçbir zaman kullanmayacağı bir olanaktır.

Alıntı:

>

programın normal çıktısı else bloğuna alınarak debug işletiminde ekran çıktısının daha temiz olması sağlanıyor. Böylece hata ayıklama süreci daha rahat olabilir.

Mantıklı. Ama programın normal işleyişinden o kadar farklı işlemesini de istemeyebiliriz.

Ali

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

« First   ‹ Prev
1 2