Forum: D Programlama Dili RSS
Enum'u Anlamak!
enum'u ehlileştirmek başlığından devam...
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ı: Enum'u Anlamak!
Merhaba,

Az önce yanlış anlamları engellemek ve doğruyu kavramak için küçük bir deneme kodu yazdım. Meğer enum, bilgisayarın kapasitesine (32 bit/64 bit) göre adreslenebilen sanal bir SINIR'a yerleştirilen sabit değişmezlerden (immutable) ibaretmiş.

Yani bunu bir cetvel veya sayı ekseni gibi düşünebilirsiniz. Her sayı çizgisine yerleştirilen (işaretlen) bir isimler topluluğumuz var. Ancak kural gereği bunlar arasında sayıları yok farzedemiyoruz. Onlar hala orada; sadece isimsizler. Bakınız şu kod bunu kanıtlıyor:

import std.stdio;
 
immutable SINIR = size_t.max;
 
enum Say {
    Bir = 1, Son = SINIR
}
 
void main() {
    Say deneme = Say.Bir;
 
    writeln ("SINIR = ", SINIR);
    writeln(" - ", deneme);
 
    for ( ; deneme != SINIR; deneme++) 
        if (deneme % (SINIR / 8) == 0) writefln("\t%d", deneme);
 
    writeln(" - ", deneme);
}
ÇIKTISI:
SINIR = 4294967295
 - Bir
        536870911
        1073741822
        1610612733
        2147483644
        -1610612741
        -1073741830
        -536870919
        -8
 - Son


Dip Not: Bu kod 32 bit sistemde denenmiştir. Muhtemelen 64 bit sistemde bu sayılar daha büyük olacak ve işlem daha uzun sürecek.

Sevgiler, saygılar...
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
Avatar
Salih Dinçer #2
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Aynı kodu C#'da denedim de belki eksi (-) int.MaxValue'den başlatsaydım 2³²-1 kadar bir kapasite olacaktı. Bunda ise 2³¹-1 kadar bir alana değer yerleştiriyor:
using System;
 
namespace applications {
    class test {
        const int SINIR = int.MaxValue;
 
        enum Say {
            Bir = 1, Son = SINIR
        }
        
        static void Main(string[] args){
            Say deneme = Say.Bir;
 
            Console.WriteLine ("SINIR = {0}", SINIR);
            Console.WriteLine (" - {0}", deneme);
 
            for ( ; (int)deneme != SINIR; deneme++)
                if ((int)deneme % (SINIR / 8) == 0) Console.WriteLine("\t{0}", deneme);
        
            Console.WriteLine (" - {0}", deneme);
        }
    }
}
Diğer dillerde nasıl bilmiyorum, denemedim ama D'de SINIR'a ulaşıldığı zaman bir anda size_t'nin eksisine ışınlanıp 0'a yaklaşıyor. Bir nevi sayı ekseninin her iki ucunun bir çember çevresinde birleşmesi gibi.
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-05-20, 01:35.
Avatar
Salih Dinçer #3
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Çıktısını unutmuşum!

Ayrıca eklemeliyim; VS uint'e izin vermiyor. Overloading falan fıstık diyor. D'de ise sanki taşmaya izin verdiği gibi tür dönüşümüne gerek bırakmıyor. D çok güzel ve esnek bir dil...:)

"C# ÇIKTISI":
SINIR = 2147483647
 - Bir
        268435455
        536870910
        805306365
        1073741820
        1342177275
        1610612730
        1879048185
        2147483640
 - Son
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #4
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üzel deneyler... :)

Ek olarak, kaç bitlik mimaride olursa olsun D'de enum'un asıl türü açıkça seçilebiliyor. Şu enum'un değerleri 8 bitten oluşurlar:

enum Renk : ubyte { mavi, yeşil }

Veya S isminde bir yapı ile:

enum BirŞey : S { bir = S(0, 1), iki = S(2, 3) }

Ancak, S'nin enum olarak kullanılabilmesi için öncelikle opCmp() şarttır. ++ işlecinin uygulanabilmesi için de opUnary!"++" şarttır:

struct S
{
    int i;
    int j;
 
    int opCmp(S sağdaki) const
    {
        return (i == sağdaki.i
                ? j - sağdaki.j
                : i - sağdaki.i);
    }
 
    // Garip bir ++ davranışı
    auto ref opUnary(string op)() if( op == "++" ) {
      ++i;
      ++j;
      return this;
   }
}
 
void main()
{
    auto b = BirŞey.bir;
    ++b;
}

Burada da görüldüğü gibi, opUnary!"++" içinde oluşan değer enum'un tanımında bulunmak zorunda değil. Esneklik güzel ama senin de söylediğin gibi ara değerler yine de oradalar.

Ali
Avatar
Salih Dinçer #5
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Ali hocamın değindiği son örnek bana çok şaşırtıcı geliyor. Bunu şimdilik bir kenara bırakırsak şurada bahsettiğim yapı içindeki elemanlarla gezmek olayı için anahtar teşkil edebilir mi?
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ı
Enum'ları biraz daha anlamak için şu başlığı da takip etmelisiniz...:)

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

Ama her şeye rağmen anlayamadığımız veya dilin bize olanak olarak vermesini gerektiğini düşündüğümüz davranışları var. Belki de bir olanak vardır ve ben, onu henüz bilmiyorumdur?

Örneğin şu örnek derlenmez:
import std.stdio;
 
enum Günler: int {
    Pazartesi = 2,
    Salı      = 3,
    Çarşamba  = 5,
    Perşembe  = 7,
    Cuma      = 11,
    Cumartesi = 13,
    Pazar     = 17
}
 
void main() {
  Günler gün = Günler.Cuma;
  byte test = gün;/* Derlenmesi için bu satırı gizlemelisiniz...
  int test = gün;//*/
  
  typeid(gün).writeln();
}/*
Derleme Hatası:  cannot implicitly convert expression (gün) of type Günler to byte
*/
Çübkü int türündeki bir sabiti byte türündeki test değişkenine eşitlemeye çalışıyoruz. Eşitliğin sol tarafındaki tür eşitlenene göre küçüktür. Ancak burada anlamaya çalıştığım, derleyici enum'un bir int türü olduğunu biliyorsa ve/veya bize haber verebiliyorsa tür şablonu kullanarak ve is işleçi ile biz bunu sorgulayabilmeliyiz, değil mi?
bool testType(T)() if(is(T == int)) {
  return true;
}
Tamam, testType!int ile bunu yapabiliyoruz. Ama işin içine enum girince bize bildirlen sadece adı ya peki kurulurken ki türü?

Sevgiler, saygılar...
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ı
Salih Dinçer:
tür şablonu kullanarak ve is işleçi ile biz bunu sorgulayabilmeliyiz, değil mi?

Evet: std.traits.OriginalType;

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:
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, 00:17:46 (UTC -08:00)