Forum: Ders Arası RSS
with() Deyimi Örnekleri
Avatar
Salih Dinçer #1
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: with() Deyimi Örnekleri
Merhaba,

Tek amacım karşılaştığım örnekleri bu başlıkta toplamak. Gerçi Ali hocam, with() deyimine karışık duygular beslediğini ifade etmişti. Belki bu duygularını, bu vesileyle pozitife çevirebiliriz niyetindeyim. Hem D dilinin bu olanağını daha çok dillendirmiş ve haberdar olan sayısını arttırmış olacağız.

Aslında farkında olmadan ilk örneği keşfetmiş ve nakletmişim: İç içe with() deyimi...

Peki ya buna ne demeli: İsimsiz Sınıf !!!
class S {
    int a;
 
    this() {
        a = 1;
    }
}
Yukarıdaki gibi basit bir sınıfımız olduğunu varsayalım. Hem geliştirme aşamasında hem de kullanım sırasında sık sık ismini yazmak yerine (çünkü bunun ismi tek haflik olmayabilirdi!) with() deyimi ile isimsiz kullanabilir. Ama önce alıştığımız halini görelim:
void main() {
    auto i = new S();
    i.a.writeln;
    i.a = 10;
    i.a.writeln;
}
Gördüğünüz gibi satır sayısında bir değişiklik yok. Hatta güzel parantez ile arttığını da düşünebiliriz. Tek esprisi new ile hafızada yeni yer açılan (kopyası mı Ali hocam?) sınıfı with() ile kapsamamız ve bunu kümeleştirerek istediğimiz yere kadar uzatabilmemiz.
void main() {
    with(new S) {
        a.writeln;
        a = 10;
        a.writeln;
    }
}
Bu deyimi aşağıdaki gibi tek satır da kullanabiliyoruz ama sanki o zaman tüm esprisi gidiyor gibi, ne dersiniz? Gerçi biraz düşünürsek tek satırda (noktalı virgülü saymazsak) hiç bir zaman yapamayacağımız bir şey yapıyoruz...:)
    with(new S) a.writeln;
Bakın bu son söylediğimi ben de yeni farkettim! Aslında isteseydik this() içinde benzer bir şey yapılabilirdi, bilemiyorum. Ne olursa olsun bu with() deyimi gerçekten çok faydalı. Acaba başka dillerde bu olanka var mıydı?

Sevgiler, saygılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Bu mesaj Salih Dinçer tarafından değiştirildi; zaman: 2012-06-16, 00:59.
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ı
Güzelmiş. :)

Salih Dinçer:
Tek esprisi new ile hafızada yeni yer açılan (kopyası mı Ali hocam?)

Hayır, with kopyaya neden olmuor. Yalnızca 'a' gibi isimlerin nerede bulunacaklarını bildirmiş oluyoruz.

Ama söylediğini anlıyorum. Şu iki satır:

    with(new S) {
        writeln(&a);
        writeln(&a);
    }

aşağıdaki iki satırın eşdeğeri değil, çünkü aşağıdakinde iki nesne var; yukarıdakinde ise tek. Bunu a'ların adreslerini yazdırarak görebiliyoruz. Yukarıdakinde aynı adres, aşağıdakinde iki farklı adres var.

    with(new S) writeln(&a);
    with(new S) writeln(&a);

Acaba başka dillerde bu olanka var mıydı?

Galiba Pascal'da varmış.

Ali
Avatar
Salih Dinçer #3
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Anlıyorum...

acehreli:
Acaba başka dillerde bu olanka var mıydı?

Galiba Pascal'da varmış.

Ali
Hayret, sıkı bir Pascal hayranıyım ama daha önce duymamıştım. Belki de o kadar derin ilgilenmemiş olabilirim. Oysa çok tatlı şeyler, özellikle işin için OOP varsa; ve ayrıca uzun başlangıç değerleri soldaki sütunun çoğunu götürüyorsa. Çalışmayan rasgele bir örnek vereyim:

with(foo.bar.icecream) diye tatlı mı tatlı bir nesnemiz (dondurmamız) olsun!

Biz önce bunu yiyeceğiz, sonra tat alma duyumuz ile beynimizde karmaşık bir işlem yapacağız ve gülümseyeceğiz...:)
with(foo.bar.cream) {
    eating(cup);
    parameter((sin.x / cos.x)*sqrt(2));
    smile();
}
Ne kadar hoş değil mi?

Çünkü odaklamanız gereken satırlar sağa doğru kaymayıp bir küme içerisinde (bunu OOP'da çok görüyoruz) satırları derli toplu hale getiriyoruz. JSON bunun bir örneği, bir de GtkD'ye bakalım...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #4
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Merhaba,

Şurada yer alan son örneği with() ile aşağıdaki gibi derli ve toplu bir hale getirebiliriz:
import gtk.Window, gtk.Main, gtk.Widget, std.c.process;
 
int main(string[] args) {
    Main.init(args);
 
    with(new Window("[X] Düğmesine Bas ve Program Sonlandırılsın!")){
        setSizeRequest(450, 450);
        setResizable(false);
        addOnHide( delegate void(Widget aux){ exit(0); });
        show();
    }
    Main.run;
    return 0;
}
Tabi oluşturulan pencere nesnesini (burada isimsiz veya anonim görünmekte), küme dışında başka yerde kullanmayacağımızı da belirtmek isterim. Yani with() ile beraber oluşturduğumuzda nesne orada oluşuyor. Peki ya ölüyor mu? Denemek lazım...:)

Başarılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #5
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ı
Salih Dinçer:
Yani with() ile beraber oluşturduğumuzda nesne orada oluşuyor. Peki ya ölüyor mu?

Referans türlerinde nesne artık geçersizdir. Sonlandırıcı işlevi ilerideki belirsiz bir zamanda işletilir (veya hiç işletilmez).

Değer türlerinde ise sonlandırıcısı hemen çağrılır.

import std.stdio;
 
struct S
{
    int i;
 
    this(int i = 0) {
        writeln("kuruldu");
    }
 
    ~this() {
        writeln("sonlandı");
    }
}
 
void main()
{
    with(S(1)) {
        writeln("with içinde");
        i = 42;                  // <-- HATA
    }
 
    writeln("with dışında");
}

İsimsiz nesnenin yaşamı with'e girmeden sonlanıyor. Çıktısı:

kuruldu
sonlandı
with içinde
with dışında


Görüldüğüne göre with nesnelerin yaşamlarını kendi bloğu kadar uzatmıyor. Bunun bir dmd veya tasarım hatası olup olmadığını bilmiyorum.

Buna bakarak, bence new ile oluşturulan nesnenin geçerliliği de with parantezinde son buluyor. Teorik olarak with'in bloğuna girmeden o da sonlanıyor olabilir.

Ali
Avatar
Salih Dinçer #6
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Evet bunu ben de farkettim; with() içinde struct kullanırken bir uyumsuzluk var...

Denediğim benzer bir örneği, yukarıdaki örneğe sınıf olarak uyarlarsak:
import std.stdio;
 
class S {
    static int i;
 
    this(int i = 0) {
        writefln("%s kurulduğu anda S.i = %d", this, i);
    }
     ~this() {
        writefln("%s silinmeden önce S.i = %d", this, i);
    }
}
void main() {
    with(new S(1)) {
        writefln("\twith() içindeyken i = %d @%x", i, &i);
        i = 42;
    }   writefln("\twith() dışındayken i = %d @%x", S.i, &S.i);
}/* Çıktısı:
struct2.S kurulduğu anda S.i = 1
    with içindeyken i = 0 @b786a6c8
    with dışındayken i = 42 @b786a6c8
struct2.S silinmeden önce S.i = 42
*/
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
zafer #7
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #2
acehreli on 2012-06-16, 02:32:
Galiba Pascal'da varmış.

Pascal'da olduğunu bende bilmiyordum. With ile ilk Delphi ortamında tanışmıştım yaklaşık D dilindeki gibi bir kullanıma sahip, sanırım başka dilllerdede benzerleri var. Örneğin C# tarafından sağlanan using olanağı bence with olanağının çok daha ilerisine geçmiş kullanışlı bir olanak temelde birbirinin eşdeğeri iki özellik aslında.
https://github.com/zafer06 - depo
acehreli (Moderatör) #8
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ı
Yanıtlanan mesaj #5
acehreli on 2012-06-16, 11:18:
Görüldüğüne göre with nesnelerin yaşamlarını kendi bloğu kadar uzatmıyor. Bunun bir dmd veya tasarım hatası olup olmadığını bilmiyorum.

D.learn haber grubunda da dmd hatası olduğu düşünüldü. Şu hatayı açtım:

  http://d.puremagic.com/issues/show_bug.cgi?id=8269

Ali
Avatar
Salih Dinçer #9
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Teşekkürler Ali Hocam,

Sayende bir böcüğümüz oldu sonunda...:)

Şurada tartışma devam edebilir: http://forum.dlang.org/thread/jrqe6e$1gej$1@digitalmars.com
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #10
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yanıtlanan mesaj #8
Yeni şeyler öğrendim...:)

Paylaşmadan önce ihmal ettiğim eski bir örnek (hatta ilk!): with deyiminin switch ile kullanımı

Bunu Ali hocam paylaşmıştı ve en üstte olmayı hak ediyordu. Örneğin itibarını az olsa iade etmiş oldum mu? Sanmıyorum ama bir hatam olduysa affola...

acehreli on 2012-06-19, 13:56:
acehreli on 2012-06-16, 11:18:
Görüldüğüne göre with nesnelerin yaşamlarını kendi bloğu kadar uzatmıyor. Bunun bir dmd veya tasarım hatası olup olmadığını bilmiyorum.
D.learn haber grubunda da dmd hatası olduğu düşünüldü. Şu hatayı açtım:
http://d.puremagic.com/issues/show_bug.cgi?id=8269
Bu hatayı araştırırken düzeltilmiş başka bir şu hatayı buldum:
http://d.puremagic.com/issues/show_bug.cgi?id=6128

Öyle sanıyorum ki bizim yayınladığımız destructed hatasına doğrudan bu hata etki ediyor. En azından düzeltme yapılan yerinde küçük bir püf noktası (while ile do while arasındaki nüans gibi) var. Her neyse with'in takipçisi olmaya devam edeceğim...:)

Bu vesileyle iki hatayı düzelttim daha doğrusu bunların hata olmadığını zannediyorum:
http://d.puremagic.com/issues/show_bug.cgi?id=1759
http://d.puremagic.com/issues/show_bug.cgi?id=8414

İlkinde bir delegate kurmuş ve int türünde işlev döndürmek istemiş. Ama bunu ters yapmış yani return'ü başta kullanacağına with'den hemen sonra icra etmiş. Bilemiyorum, derleyicinin kafası mı karışıyor...:)
struct SS{ int a, b, c; }
int delegate() addss(SS obj)
{
    with(obj) return {
        return a+b+c;
    };
}
Çünkü yeni olan ikinci örnekte de with'den sonra if kullanmış! Sanki birbirlerine benziyor ve küme parantezlerinden önce deyim girmiş gibi görünüyorlar. Hataları kapatmakla iyi mi yaptım bilemiyorum ama bunlar hata değil...
void main()
{
    Enum en;
    with (Enum)
    if (matchAny(en, en1, en2)) { }
}
alias'la ilgili son bir şey daha öğrendim ama bunu başka başlıkta bahsetmeliyim... ;-)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #11
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ı
Salih Dinçer:
İlkinde bir delegate kurmuş ve int türünde işlev döndürmek istemiş. Ama bunu ters yapmış yani return'ü başta kullanacağına with'den hemen sonra icra etmiş.

Eğer D'nin kuralı senin söylediğin gibi olması gerektiğini söylüyorsa haklısın. Ama öyle demiyorsa veya dese bile kodu yasalmış gibi kabul ediyorsa bir yerde bir hata var demektir.

ikinci örnekte de with'den sonra if kullanmış! Sanki birbirlerine benziyor ve küme parantezlerinden önce deyim girmiş gibi görünüyorlar.

O konuyu da iyice açıklamaları gerek. with'in her zaman için küme parantezi ile kullanılması gerekiyorsa ya kod derlenmemeli ya da küme parantezi kullanıp kullanmamak bir fark doğurmamalı.

Ali
Avatar
Salih Dinçer #12
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli on 2012-08-08, 09:34:
Eğer D'nin kuralı senin söylediğin gibi olması gerektiğini söylüyorsa haklısın. Ama öyle demiyorsa veya dese bile kodu yasalmış gibi kabul ediyorsa bir yerde bir hata var demektir.
Evet, gerçekten de bir hata var gözüküyor. Hata raporunu tekrar açmışlar ve ben de kabül etmek zorunda kaldım...:)

Çünkü şunları denedim:
Sample-1:
void main()
{
    Enum en;
 
    with (Enum)  // <-- ERROR: found '}' instead of statement
 
}

Düşündüm ki if() gibi with() de parantezsiz kullanıma izin verebilir...

Sample-2:
void main()
{
    Enum en;
 
    with (Enum); // <-- ERROR: use '{ }' for an empty statement, not a ';'
 
}

Ancak bir semicolon olmak zorundadır ve tek başına olduğunda küme parantezleri kullanılmalıdır. O yüzden D yukarıdaki kod parçacığına da izin vermez...

Surprised:
void main()
{
    Enum en;
 
    with (Enum) // <-- NO ERROR!
    if(true) en1.writeln;
}
Ancak biz bunu bir if() ile sonlandırırız ve de çalıştığınız görürüz...:)

Böyle sürprizler ile karşılaşınca with()'e güvenim sarsılıyor. En iyisi dikkatli kullanmalı...

O konuyu da iyice açıklamaları gerek. with'in her zaman için küme parantezi ile kullanılması gerekiyorsa ya kod derlenmemeli ya da küme parantezi kullanıp kullanmamak bir fark doğurmamalı.

Meğer hata burada değilmiş; küme parantezi olmadan da çalışabilen bir kodu başka şekillerde de çalışabilmesiymiş. Öyleyse son kod parçacığının çalışması bizi linker hatasına götürüyor. Öyle değil mi?
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #13
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ı
Örneklere geçmeden önce with'in D dilindeki tanımına bakalım:

  http://dlang.org/statement.html#WithStatement

Üç geçerli kullanımı varmış:

  • with ( Expression ) ScopeStatement

  • with ( Symbol ) ScopeStatement

  • with ( TemplateInstance ) ScopeStatement

Parantez içine gelenleri bir kenara bırakalım çünkü hepsinde de with'den sonra ScopeStatement geliyor. Onun tanımına geçiyorum:

  http://dlang.org/statement.html#ScopeStatement

  • NonEmptyStatement

  • BlockStatement

Önce NonEmptyStatement'a bakalım:

  • NonEmptyStatementNoCaseNoDefault

  • CaseStatement

  • CaseRangeStatement

  • DefaultStatement

Bunlar arasından birincisinin tanımı çok kalabalık ama senin örneğindeki if'li kullanımı kapsıyor:

import std.stdio;
 
enum Enum { en1 }
 
@property void writeln(Enum e)
{
    std.stdio.writeln(e);
}
 
void main()
{
    Enum en;
 
    with (Enum) // <-- NO ERROR!
        if(true) en1.writeln;
}

O tamam. Dilin yazım kurallarına uyuyor. Öte yandan tek noktalı virgül yasal değil çünkü dilin yazım kurallarında geçmiyor. Aynı biçimde with()'den sonra hiçbir şey gelmemesi de yasal değil çünkü o durum da dilin yazım kurallarında listelenmemiş.

Salih Dinçer:
Böyle sürprizler ile karşılaşınca with()'e güvenim sarsılıyor. En iyisi dikkatli kullanmalı...

Programcılık zor iş; hep dikkatli olmalıyız :) ama bu konudaki sürpriz, beklentilerimizin dilin kuralları dışında kalmasından kaynaklanıyor.

Bu incelemeyi tamamlamak için with'in altına gelebilecek bir de BlockStatement'a bakalım:

  http://dlang.org/statement.html#BlockStatement

Onun her iki seçeneği de küme parantezlerini gerektiriyor:

  • { }
  • { StatementList }

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:
Forum: Ders Arası RSS
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-20, 01:18:58 (UTC -08:00)