Forum: D Programlama Dili RSS
Gruplama düzen belirteçleri %( ve %)
Sayfa:  önceki  1  2 
acehreli (Moderatör) #16
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 ID 9065
Salih Dinçer:
meğer son elemanı yutuyormuş.

Evet, enum'larda böyle bir sorun var. Sınır belirleyen başka olanaklarda sondaki değer hep aralığın dışında kalıyor ama enum.max aralığa dahil. Aslında enum.end gibi başka bir nitelik daha gerekiyor gibi... Ama aşağıda senin kodunda da görüldüğü gibi bu da çözüm değil.

        for(T x = T.min; x <= T.max; x++) {

T'nin int olduğunu düşünelim ve T.max==int.max olsun. O döngü sonsuza kadar takılır, değil mi?

Ama anlayamadığım bir şey de main() içinde foreach() ile kullandığınızda yine aynı çıktıyı almanız...

Yani şu kod Pazar'ı da yazdırıyor diyorsun:
    foreach (gün; [ EnumMembers!Günler ]) {
        writeln(gün);
    }
Öyle çünkü foreach aralıktaki bütün elemanlar için işletilir. EnumMembers enum'un son değerini de içeren bir aralık oluşturur. Bizim yaptığımız gibi ++ işleciyle değil. Zaten enum değerleri arasında boşluk olsa ++ işlemez. EnumMembers öyle değil.

Bu başlıktaki bir çok öğeyi belki de Enum'u Anlamak başlığına taşımalıyız, ne dersiniz?

Bu konuda konuşuldukları için bütünlük açısından bunun parçası olarak kabul edilmeliler. Örneğin, son yazdığın yazı bile "Yukarıdaki kodu" diye başlıyor. O zaman o kodu içeren yazıyı da mı seçip başka konuya taşımalıyız? Ya o da bir biçimde öncekilere bağlıysa? :) Bence daha iyisi, çok sayıda ama kısa konular açmak. Daha sonradan bir şeyleri arayınca sayfalar süren bir konu içinde dolaşmak kolay olmuyor.

Konuyu sen açtığın için senin yazdığın bir yazıyı örnek vereyim: Bu konu içinde "Konuyla alakasız ama" diye başlattığın bir yazı da var. ;)

Ali
Avatar
Salih Dinçer #17
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
T'nin int olduğunu düşünelim ve T.max==int.max olsun. O döngü sonsuza kadar takılır, değil mi?
Sıralı giden enum'lar için kim işaretli veri türü kullanır ki...:)

Bu durumda sözleşmeli programlama yapmaktan başka aklıma bir şey gelmiyor. Ama enum'un ismi bana tür olarak geliyor ve şu ana kadar edindiğim bilgiler ile iki nokta üst üste (enum Günler:)'den sonraki tür değerini sorguya tabi tutamıyorum:
    import std.typetuple;
 
    template testType(T) {
      alias TypeTuple!(int, byte, short, long) types;
      bool test() {
          foreach(t; types) {
              //if(typeid(T) is typeid(t))/*
              if(is(T == t))//*/
                  return false;
          }
          return true;
      }
      enum testType = test();
    }
    
    auto enumMembers(T)() in {
      assert(testType!T, "\n\n\t"
                         "You should use unsigned data types!\n");
    } body { //*/{
      string[] result;
      bool casting = true;
 
      for(T x = T.min; x <= T.max; x++) {
        auto value = appender!string();
        formattedWrite(value, "%s", x);
        foreach(char c; value.data) {
          if(c < 0x2F) { // içinde parantez varsa görmezlikten gel
            casting = false;
            break;
          }
        }
        if(casting) result ~= value.data;
        casting = true;
      }
      return result;
    }
 
import std.stdio;
 
void main() {
  enum Günler: uint {
    Pazartesi = 2, Salı=3, Çarşamba=5, Perşembe=7, Cuma=11, Cumartesi=13, Pazar=17
  }  
  writefln("%-(%s, %)", enumMembers!Günler);
}
Neyse, bu arada bir geliştirme daha yaptım. Hani olur ya üyeler arasındaki değerleri sıralı olmaz. Bu durumda foreach() ile yaptığımız sıralı mantık fena halde çuvallar. Çünkü enum'un üyesi olmayan değerleri (örn. cast(Günler)4) döndürmeye başlıyor. Bunu ise çok basit bir şekilde içinde alfasayısal olmayan karakterlere rastladığında result dizgesine eklemeden önleyebiliyoruz.

Teşekkürker...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #18
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Az önce std.random'a bakıyorken std.traits içinde isUnsigned isminde bir şablon dikkatimi çekti.:
traits.d:
/**
Detect whether $(D T) is a built-in unsigned numeric type.
 */
template isUnsigned(T)
{
    enum bool isUnsigned = is(UnsignedTypeOf!T) && !isAggregateType!T;
}
Bu ne güzel şablonmuş öyle...:)

İşimize yarıyor ve çok güzel çalışıyor. Zannedersem bunun sebebi IntegralTypeOf şablonu içindeki şu kısım:
    static if (is(T == enum))
        alias .IntegralTypeOf!(OriginalType!T) IntegralTypeOf;
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: 2013-03-10, 11:51.
Değişiklik nedeni: IntegralTypeOf notu eklendi...
acehreli (Moderatör) #19
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 #17
Salih Dinçer:
Sıralı giden enum'lar için kim işaretli veri türü kullanır ki...:)

Aynı sorun işaretsiz türlerde de var. .max'ı bir arttırınca tekrar .min'den başlar. Şu döngü hiç sonlanmaz:
import std.stdio;
import std.conv;
 
auto foo(T)() {
    string[] result;
    for(T x = T.min; x <= T.max; x++) {
        result ~= x.stringof;
    }
    return result;
}
 
enum E : size_t { a = size_t.max - 2, b, c }
 
void main()
{
    foo!E();
}

Bu durumda sözleşmeli programlama yapmaktan başka aklıma bir şey gelmiyor.

EnumMembers'ı nasıl yazmışlar acaba?

iki nokta üst üste (enum Günler:)'den sonraki tür değerini sorguya tabi tutamıyorum:

std.traits.OriginalType'mış:
import std.traits;
// ...
    assert(is(OriginalType!E == size_t));

Ali
Avatar
Salih Dinçer #20
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
EnumMembers'ı nasıl yazmışlar acaba?
Çok fena yapmışlar...:)

template EnumMembers(E) if (is(E == enum)) {
 
    template WithIdentifier(string ident)  {
        static if (ident == "Symbolize") {
            template Symbolize(alias value) {
                enum Symbolize = value;
            }
        } else  {
            mixin("template Symbolize(alias "~ ident ~") {"
                 ~"    alias "~ ident ~" Symbolize;"
                 ~"}");
        }
    }
 
    template EnumSpecificMembers(names...)  {
        static if (names.length > 0)  {
            alias TypeTuple!(
                    WithIdentifier!(names[0])
                        .Symbolize!(__traits(getMember, E, names[0])),
                    EnumSpecificMembers!(names[1 .. $])
                ) EnumSpecificMembers;
        } else {
            alias TypeTuple!() EnumSpecificMembers;
        }
    }
    alias EnumSpecificMembers!(__traits(allMembers, E)) EnumMembers;
}
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #21
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ı
Yaşlanıyoruz. :) Şurada incelemiştik:

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

Ali
Avatar
Salih Dinçer #22
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
O başlığı hatırlıyorum hocam ama nedense forumda aramak yerine kodu yapıştırmak kolay geldi...:)

Bu arada yeni bir çözüm ürettim, nedense int'den küçük türlerde doğru çalışıyor. Aslında hepsinde doğru çalışması gerekiyor ama çözemedim. Küçük bir yerde hata veya püf noktası olabilir. O yüzden izlenimlerinize sunuyorum:
  import std.stdio;
  import std.conv;
 
  alias short enumTürü;
 
  enum Günler: enumTürü {
                            Pazartesi = 2,
                            Salı      = 3,
                            Çarşamba  = 5,
                            Perşembe  = 7,
                            Cuma      = enumTürü.max - 2,
                            Cumartesi,
                            Pazar
                        }
 
  auto enumMembers(T)(){
    string[] result;
 
    T x = T.min;
    do {
      result ~= to!string(x);
      foreach(char c; result[$-1]) {
        if(c < 0x2F) { // içinde parantez varsa görmezlikten gel
          result = result[0..$-1];
          break;
        }
      }
      if(x != T.max) x++; else break;
    } while(x <= T.max);
 
    return result;
  }
 
void main() {
  writefln("%-(%s, %)", enumMembers!Günler);
}
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #23
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ı
Kısa cevabım için kusura bakma ama sen bunu kesin çözersin. :) Bir yerlere writeln vs. sıkıştırsan hemen anlaşılır herhalde.

Başka hata var mı bilmiyorum ama foreach ile ilerlemekte olduğun aralığı değiştirmek doğru değil:
        foreach(char c; result[$-1]) {
            if(c < 0x2F) {
                result = result[0..$-1]; // <-- HATA: foreach'in işi bozulur 
Ali
Avatar
Salih Dinçer #24
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Estağfirullah hocam, aksine hızlı cevap için teşekkür ederim. Ama cevap verdiğinden bu yana ara sıra bakıyorum da tık yok...:)

Gerçi sorun da yok; şöyle ki:

İçeriğinde parantez olan bir dizge ile karşılaştığı zaman onu result dizisinden çıkardığım gibi break ile döngüden de çıkıyorum. Sanırım tek sorun yavaşlık çünkü örnek çok absürd! Düşünsenize; 7'den neredeyse uint.max'a kadar:
  • Gereksiz yere x dizgeye çevriliyor
  • Sonra dizi büyüyor
  • Eklenen bu dizgenin 5. karakterinde "(" işaretiyle karşılaştığı için
  • Dizi küçültülüyor
  • Döngüden çıkılıp başa dönülüyor

Ben bu satırları yazıyorken yukardaki işlemler arka planda yapılıyor. Ne zaman biter bilmiyorum ama bitince haber veririm...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #25
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bitmek bilmeyince bir test koduyla ve daha hızlı olacağını düşündüğümden std.algorithm.find ile denedim:
  enum sınır = int.max/100;
  auto enumMembers(T)(){
    string[] result;
   
    T x = T.min;
    do {
      auto str = to!string(x);
      if(std.algorithm.find(str, '(').empty) result ~= str;
      if(x != T.max) x++; else break;
      //* TEST CODE
      if(x % sınır == 0) {
        writefln("%s%% completed", (cast(int)x) / sınır);
      }//*/
    } while(x <= T.max);
 
    return result;
  }
Sonuç tahmin ettiğim gibi saatler alan bir bir işlem. Ben tıkandım...:(
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #26
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Son olarak göz korkutmasın diye belirtmeliyim...:)

İşlevimiz başlangıçtan bu yana yeteneği artarken çok sadeleşti:

  auto enumMembers(T)(){
    string[] result;
    T x = T.min;
 
    do {
      auto str = to!string(x);
      if(std.algorithm.find(str, '(').empty) result ~= str;
      if(x != T.max) x++; else break;
    } while(x <= T.max);
 
    return result;
  }

Topu topu 5 satırlık bir döngü içinde geçici 1 değişken ve 2 de işlev değişkeni...:D
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #27
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ı
Evet, ++ işleciyle olmayacağı açık. :) Biz de EnumMembers'ın kullandığı allMembers'dan yararlanabiliriz:
import std.stdio;
 
alias int enumTürü;
 
enum Günler: enumTürü {
    Pazartesi = 2,
    Salı      = 3,
    Çarşamba  = 5,
    Perşembe  = 7,
    Cuma      = enumTürü.max - 2,
                Cumartesi,
                Pazar
                }
 
auto enumMembers(E)() {
    string[] result;
 
    foreach (e; __traits(allMembers, E)) {
        result ~= e;
    }
 
    return result;
}
 
void main()
{
    writefln("%-(%s, %)", enumMembers!Günler);
}
Çıktısı:

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

Daha da kısa:
import std.algorithm;
import std.conv;
// ...
auto enumMembers(E)() {
    return [ __traits(allMembers, E) ].map!(a => a.to!string);
}

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

Şablonlara bu kadar kolay teslim olmayacağım; 2. raunda başka başlıkta devam edelim...:)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #29
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ı
Başka yolla yapabileceğini sanmıyorum. __traits aslında bir kütüphane olanağı değil; yani bizim de yazabileceğimiz bir olanak değil. Doğrudan, derleyicinin elindeki bilgiden yararlanma olanağı sağlıyor. Biz içinde bulunduğumuz kaynak kodu tarayamadığımız için ancak __traits var. (Belki ileride AST macros denen olanak gelirse o zaman o ağaçta ilerleyebiliriz ama şimdilik benim bildiğim kadarıyla olanaksız.)

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

Bugün bir ara assembly kodlarına baktım da, yanlış hatırlamıyorsam her bir üye için bir desteden fazla satır kod yapıştırıyor. Yani 10 üye varsa bir satır veriyi ekrana yazabilmek için 100'den fazla satır koşuyor. Üstelik iki tane call olduğunu düşünürsek aynı alt yordamlara her bir üye için defalarca giriyor...:(

Sevgiler, saygılar...
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:  önceki  1  2 
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-21, 15:18:11 (UTC -08:00)