Forum: D Programlama Dili RSS
Gruplama düzen belirteçleri %( ve %)
Sayfa:  1  2  sonraki 
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ı: Gruplama düzen belirteçleri %( ve %)
Phobos'a yakın zaman önce eklenen ve henüz kitapta yer almayan %( %) belirteçleri var. Bir grup elemanı yazdırırken kolaylık sağlıyor. Nasıl kullanıldığını anlamak için önce kendi bildiğimiz gibi yazdıralım.

Amaç, günleri aralarında virgül (ve boşluk) olacak biçimde yazdırmak. Hepsini de küme parantezleri arasında istiyoruz. Ve tabii günlerin başında veya sonunda başı boş virgül olmasın:

import std.stdio;
import std.array;
 
void main()
{
    auto günler = [ "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma",
                    "Cumartesi", "Pazar" ];
 
    auto dilim = günler;
 
    write("{");
 
    if (!dilim.empty) {
        // İlk günden önce ", " yazdırmayacağız
        write(dilim.front);
        dilim.popFront;
 
        foreach (gün; dilim) {
            writef(", %s", gün);
        }
    }
 
    writeln("}");
}

Çıktısı:

{Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar}

Şimdi aynı programı %( ve %) belirteçleri ile yazdıracağım:

import std.stdio;
 
void main()
{
    auto günler = [ "Pazartesi", "Salı", "Çarşamba", "Perşembe", "Cuma",
                    "Cumartesi", "Pazar" ];
 
    writefln("{%-(%s, %)}", günler);
}

Çıktısı aynı! :D

Oradaki tire karakterini şimdilik bir kenara bırakırsanız, şöyle çalışıyor: Düzen dizgisinin %( ve %) belirteçleri arasındaki parçası parametre olarak verilen topluluğun bütün elemanlarına ayrı ayrı uygulanıyor.

Yani, "%s, " düzen dizgisi günler'in içindeki her gün için ayrı ayrı kullanılıyor. %s'ten sonra gelen bölüm, yani ", " ayraç olarak algılanıyor. Hem de, önceki programda yaptığımız gibi akıllı bir biçimde: O ayraç sonuncu elemana uygulanmıyor! :)

Tire kullanılmadığında dizgiler ve karakterler tırnaklar içinde yazdırılıyor. Onun için ben tire kullanmayı seçtim.

Bir nokta daha var: %s'ten sonra gelen karakterlerin (yani ", " karakterlerinin) hepsinin birden otomatik olarak ayraç kabul edilmeleri istenmediğinde ayracın nerede başladığı %| belirteci ile bildiriliyor.

Bunun örnekleri std.format belgesinde var:

  http://dlang.org/phobos/std_format.html

Ali
Bu mesaj acehreli tarafından değiştirildi; zaman: 2012-10-10, 01:54.
Avatar
mert #2
Üye Ara 2010 tarihinden beri · 194 mesaj
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı

Belirteçleri dün inceledim daha bir kaç örnek ile de değerlendirdim. Kitaba girecek mi?
mert
Avatar
Salih Dinçer #3
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bu yöntemle 'enum'ları da yazdırabilseydik hoş olurdu. Şöyle bile hata verdi:
  enum günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar };
  foreach(gün; 0..günler.Pazar) writefln("{%(%s, %)}", cast(günler)gün);
Ayrıca tirenin hiç bir farkını göremedim. Bende (2.059) hep tırnaklı çıkardı...
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ı
Eh biraz uğraştırıyor ama 'enum'ları geleneksel şekilde çıktı almak mümkünmüş:
void main(){
    enum günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar };
 
    write("{ ");
    foreach(gün; 0..günler.max) writef("%s, ", cast(günler)gün);
    günler.max.writeln(" }");.writeln(" }");
 
}/*Çıktısı:
{ Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
*/
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-10-10, 05:18.
Değişiklik nedeni: günler.Pazar -> günler.max
Avatar
Salih Dinçer #5
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Burdan yola çıkarak, bu özelliği pekala enum ve diğer türler için eklemeleri mümkün. Çünkü şöyle bir işlev (function) iş görüyor:
void enumPrint(T)(T x) {
    write("{ ");
    foreach(i; T.min..T.max) writef("%s, ", i);
    T.max.writeln(" }");
}
/* Usage:
enum numbers { one, two, three }
numbers test;
enumPrint(test);
*/
Artık başka bir yolu yoksa Ali hocam bizim için elçi olursa sevinirim. Belki 2.061'e eklerler...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #6
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konuyla alakasız ama hep istediğim (hatta Ali hoca hatırlar, bir ara var olduğunu zannetmiştim...:)) ama nedense böyle faydalı bir özelliği olmadığı şu olayı DMD'ye yedirseler ne güzel olurdu:
import std.stdio;
 
    T roundInc(T)(T x) {
        if(x == T.max) return T.min;
        return ++x;
    }
 
void main(){
    enum numbers { one, two, three }
    auto test = numbers.three;
 
    test.writeln("<--normal printed");
    test.roundInc.writeln("<--was directed");
 
}/* Print Out:
three<--normal printed
one<--was directed
*/
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #7
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 #4
Salih Dinçer:
'enum'ları geleneksel şekilde çıktı almak mümkünmüş

Bu yöntemden ve EnumMembers'dan yararlanınca daha da kolay. EnumMembers'ın nasıl dizi içine yazıldığına dikkat edin; bunu bilmiyordum:

import std.stdio;
import std.traits;
 
void main()
{
    enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
    writefln("{ %(%s, %) }", [ EnumMembers!Günler ]);
}

Ali
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 #3
Salih Dinçer:
tirenin hiç bir farkını göremedim. Bende (2.059) hep tırnaklı çıkardı...

2.060 ile şöyle oluyor:

import std.stdio;
 
void main()
{
    auto dizi = [ "merhaba", "dünya" ];
    writefln("%(%s %)", dizi);
    writefln("%-(%s %)", dizi);
}

Çıktısı:

"merhaba" "dünya"
merhaba dünya


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ı
Yanıtlanan mesaj #7
acehreli on 2012-10-10, 11:47:
Bu yöntemden ve EnumMembers'dan yararlanınca daha da kolay...
enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
auto çokuz = EnumMembers!Günler;
Bu da iyimiş ama şu çokuzlara henüz alışamadım. Sıra onlarda galiba...:)
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ı
Şimdi şöyle denedim...
    enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
    auto dizi = [ EnumMembers!Günler ];
    dizi.writeln("\n^---", typeid(dizi));
Çıktısı:
[Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar]
^---enumlar.main.Günler[]

Bu bir şablon zannedersem? Ancak dizi olarak döndürülebilmesi D'nin çokuzlar ile ilgili başka bir özelliği olsa gerek. Hoş...:)
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ı
Yanıtlanan mesaj #9
Salih Dinçer:
acehreli on 2012-10-10, 11:47:
Bu yöntemden ve EnumMembers'dan yararlanınca daha da kolay...
enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
auto çokuz = EnumMembers!Günler;
Bu da iyimiş ama şu çokuzlara henüz alışamadım. Sıra onlarda galiba...:)

İkinci satırı ben yazmamışım. ;) Ayrıca tuple'a karşılık galiba "çokuzlu" diyoruz. (Çokuz da güzel olurmuş aslında.)

Bu bir şablon zannedersem?

Ünlem işaretine bakılırsa öyle:

  http://dlang.org/phobos/std_traits.html#EnumMembers

Bir "static çokuzlu" döndürüyormuş. Dizi içine yazınca dilim üretmesini ben de çok yeni öğrenmiştim.

D'de bu konuyu da ilgilendiren bir gariplik var: foreach'in bazı kullanımları aslında 'static foreach'. Ama D'de açıkça 'static foreach' diye yazılan bir şey yok.

Örneğin, aşağıdaki koddaki foreach çalışma zamanında işletilmiyor, derleme zamanında işletiliyor:
import std.stdio;
import std.traits;
 
void main()
{
    enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
 
    foreach (gün; EnumMembers!Günler) {
        writeln(gün);
    }
}
Yukarıdaki kod aşağıdakinin eşdeğeri olarak derleniyor:
import std.stdio;
import std.traits;
 
void main()
{
    enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
 
    with (Günler) {
        writeln(Pazartesi);
        writeln(Salı);
        writeln(Çarşamba);
        writeln(Perşembe);
        writeln(Cuma);
        writeln(Cumartesi);
        writeln(Pazar);
    }
}
Tabii writeln'dan başka kod olsaydı onlar da derlenmiş kodun içinde birden fazla kere bulunacaklardı. Akılda tutmakta yarar var. :)

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:
D'de bu konuyu da ilgilendiren bir gariplik var: foreach'in bazı kullanımları aslında 'static foreach'. Ama D'de açıkça 'static foreach' diye yazılan bir şey yok.

Örneğin, aşağıdaki koddaki foreach çalışma zamanında işletilmiyor, derleme zamanında işletiliyor:
        :        :        :
    foreach (gün; EnumMembers!Günler) {
        writeln(gün);
    }
        :        :        :
Sanırım bu çok normal çünkü bu bir şablon. İçeriğinde mixin'ler falan olmalı...

Cahilce bu durumu ilerleteceğim; işin içine enum giriyorsa eğer, static bir şeyler olduğunu düşünüyorum. Yani key/value olarak değerlendirirsek value kısmında hiç bir sorun yok. Ama key'leri de kullanıyorsak, elemanların isimleri static veri olarak yerleştiriliyor. Bunu assembly kodlarında görmüştüm. Ancak bu veri, çağrılabilen cinsten yani bir yerde string olarak duruyor ve o adres hafızaya alınıp ilgili işleve dallanılıyor.
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ı
Salih Dinçer:
Sanırım bu çok normal çünkü bu bir şablon.

Orası tamam. Ama foreach kendisi şablon veya mixin değil.

Buradaki gariplik, EnumMembers!Günler'in ürettiği ile kullanıldığında ortada foreach'in kalmıyor olması. Onun yerine yedi tane işlem geliyor.

Yani şu iki döngü birbirinden çok farklı:
    // Yedi adet writeln() satırı
    foreach (gün; EnumMembers!Günler) {
        writeln(gün);
    }
 
    // Çalışma zamanında yedi kere işletilen bir döngü
    foreach (gün; [ EnumMembers!Günler ]) {
        writeln(gün);
    }

İçeriğinde mixin'ler falan olmalı...

Garip olan da o: foreach mixin gibi kod üretmek için kullanılıyor. Ama bu, foreach herhangi bir şablonla kullanıldığında geçerli değil:
import std.stdio;
import std.range;
 
int[adet] birŞablon(int adet)()
{
    int[adet] sonuç;
    return sonuç;
}
 
void main()
{
    foreach (i; birŞablon!3) {
        writeln(i);
    }
}
Orada foreach bir şablonla kullanılıyor ama kod bildiğimiz sıradan bir döngü içeriyor.

Cahilce bu durumu ilerleteceğim; işin içine enum giriyorsa eğer, static bir şeyler olduğunu düşünüyorum.

Doğru. Burada ilginç olan, EnumMembers!Günler ile [EnumMembers!Günler] kullanımları arasındaki fark. İşin güzeli, foreach'in çalışma zamanında işletilmesini istiyorsak EnumMembers!Günler'in etrafına köşeli parantezler eklemek yetiyor. (Yukarıdaki karşılaştırmada olduğu gibi.)

Yani key/value olarak değerlendirirsek value kısmında hiç bir sorun yok. Ama key'leri de kullanıyorsak, elemanların isimleri static veri olarak yerleştiriliyor. Bunu assembly kodlarında görmüştüm. Ancak bu veri, çağrılabilen cinsten yani bir yerde string olarak duruyor ve o adres hafızaya alınıp ilgili işleve dallanılıyor.

Mantıklı. Nasıl olsa onlar değişmez veriler. Bellekte tek yerde durabilirler.

Ali
Avatar
Salih Dinçer #14
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Haklısın, Ali hocam...

Ama bu verdiğin örnek işlev şablonu. Benim henüz kavrayamadığım şey ise template falanca() { //... } olayı. Adamlar static if, alias ve biraz da dilim kullanarak şahaneler yapmışlar:

https://github.com/D-Programming-Language/phobos/blob/mast…

Şimdi baktım da evet, orada mixin() kullanılmış; ama yeni bir şablon oluşturmak için...:)

Benim tek yapabildiğim ise işlev şablonu ile türü işleve bildirmek. Geçen hafta ders arasında Müzik Yapalım başlığında yazdığım bir iki işlev vardı. Bunu EnumMembers şablonuna uyarladığımızda aşağıdaki gibi bir şey çıktı. Bunun tek eksiği enum'un üyeleri ardışık gitmeli. Yoksa değerleri arasında boşluk olursa onları da döndüreceği için işler karışıyor. Gerçi küçük bir koşul ile süzmek (filter) olası. Bence diğer gerçek EnumMembers şablonuna göre daha dinamik ama yavaş olabilir...:)
    import std.stdio, std.range, std.format;
 
    enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
 
    auto EnumMembers(T)()
    {
        string[] result;
        foreach(T x; T.min..T.max)
        {
            auto value = appender!string();
            formattedWrite(value, "%s", x);
            result ~= value.data;
        }
        return result;
    }
 
void main()
{
    foreach (i; EnumMembers!Günler)
    {
        writef("%s\t", i);
    }
    writef("\n");
}
Çıktısı:
Pazartesi     Salı     Çarşamba     Perşembe     Cuma     Cumartesi     Pazar
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #15
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Yukarıdaki kodu gruplama düzen belirteçi ile yazdığımızda meğer son elemanı yutuyormuş. Bu durumda küçük bir düzenlemeye ihtiyaç duyduğunu farkettim. Sadece işlevin içindeki foreach()'i geleneksel for()'a çevirdim:
    auto enumPrint(T)() {
        string[] result;
        for(T x = T.min; x <= T.max; x++) {
            auto value = appender!string();
            formattedWrite(value, "%s", x);
            result ~= value.data;
        }
        return result;
    }
Ama anlayamadığım bir şey de main() içinde foreach() ile kullandığınızda yine aynı çıktıyı almanız...

Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar,

Bu biraz şaşırtıcı olsa da kafa yormak istemiyorum...:)

Çünkü şu an başka bir sorun ile boğuşuyorum. Aslında güzel bir çözüm de buldum ama geliştirmeye ihtiyaç var. Aşağıdaki kodu bir proje için yazıyorken şablon (union(T)) kullanmadığımı farkettim. Bu durumda özelleşmiş bir union olmuş oluyor!
import std.stdio;
 
enum Günler { Pazartesi, Salı, Çarşamba, Perşembe, Cuma, Cumartesi, Pazar }
 
// rooundInc() alternatifidir:
union enumSet {
  Günler e;
 
  struct {
    size_t dizin;
    
    void opUnary(string işleç)() if(işleç == "++") {
      if(dizin < e.max) dizin++;
      else dizin = 0;
    }
  }
 
  string toString() const @property {
    return std.conv.to!string(e);
  }
}
 
void main() {
  auto test = enumSet(Günler.Cumartesi);
       test++;//test++; /* satırın 2. bölümü açılırsa başa döner */
       test.writeln();
}
Dip Not: Bu başlıktaki bir çok öğeyi belki de Enum'u Anlamak başlığına taşımalıyız, ne dersiniz?
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
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:
Sayfa:  1  2  sonraki 
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-18, 09:39:15 (UTC -08:00)