October 31, 2012

Yavaş derken neyle karşılaştırıyorsun? Tabii ki herşeyin bir bedeli var. dmd'nin şu seçenekleri işe yarayabilir:

'dmd ... -O -release -inline '

Belki Variant'ın gerçekleştirmesi yavaştır; ileride hızlanması beklenebilir. gdc veya başka bir derleyici düşünebilir.

Ali

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

October 31, 2012

Alıntı (zekeriyadurmus):

>

String ile veya herhangi bir veri türü ile karşılaştırıyorum

Ama onlar burada istenenleri karşılayamıyorlar değil mi? Yalnızca tamsayı veya yalnızca dizgi tutabilen bir tür ile her türü tutabilen Variant'ı karşılaştıramayız herhalde.

Doğrusu ben Variant'ın da doğru çözüm olduğundan emin değilim. Salih'e sorduğum soru hâlâ geçerli: Dosyadan taradık ve bir dizi Variant edindik diyelim. Daha sonra bunlarle ne yapabiliriz? Nereden bilebiliriz her Variant'ın içinde hangi asıl tür var?

Ali

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

October 31, 2012

Alıntı (zekeriyadurmus):

>

kodunu denediğimiz de ise sonuç gerçekten içler acısı

Doğru. Variant temel türlerin yanına yaklaşamaz.

Ali

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

October 31, 2012

Alıntı (zekeriyadurmus):

>

dizi toplama işlemleri oldukça uzun sürüyor

Evet, D'nin dizileri ve dilimleri çok akıllıca tasarlanmış olan çok hızlı olanaklardır. Örneğin C'nin dizileri D dizilerinin yanına bile yaklaşamaz. C++'ın vector'ü de çöp toplayıcı bulunmadığı için ekleme işlemlerinde D'den daha yavaş kalmak zorundadır.

Buna rağmen, std.array.Appender'ın daha hızlı olduğu söyleniyor. Ona bakabilirsin.

Dizilerle ilgili olarak şu makaleyi (ve orada bağlantısı bulunan İngilizcesini) öneririm:

http://ddili.org/makale/d_dilimleri.html

Alıntı:

>

Kusura bakmayın bu arada yapacağımız dilin gerçekten performanslı birşey olmasını istiyoruz. Bu yüzden bu kadar inceliyorum.

Tabii ki incelemelisiniz. :) D ile yazılmış bir D derleyicisi var. Belki onların nasıl yaptıklarına da bakılabilir:

https://github.com/azizk/dil

Alıntı:

>

her satırında <!print("asdqwewq")!> yazan 2600 satır, 60kb lık bir dosyayı parse etmeyi başlattığımda diziye sürekli değer attığım için oldukça uzun sürüyor.

Acaba beklentilerimiz mi farklı? Şöyle bir program dosyaya yazma işi de dahil olmak üzere 0.015 saniye kadar sürüyor. Yavaş mı? Herhalde başka derleyicilerle daha hızlı olabilir. (?)

import std.stdio;
import std.array;

class Komut
{
   abstract void işlet();
}

class Print : Komut
{
   string mesaj;

   this(string mesaj)
   {
       this.mesaj = mesaj;
   }

   override void işlet()
   {
       writefln("%s mesajını yazdırıyorum", mesaj);
   }
}

Komut tara(string satır)
{
   // Artık tarama nasıl oluyorsa. Ben tembellik yapacağım ve komutun 'print'
   // olduğunu varsayacağım ve yalnızca çift tırnaklar arasını alacağım.

   // Baştan kırp
   while (!satır.empty && (satır.front != '"')) {
       satır.popFront();
   }

   while (!satır.empty && (satır.back != '"')) {
       satır.popBack();
   }

   return new Print(satır);
}

void yaz(string dosyaİsmi)
{
   auto dosya = File(dosyaİsmi, "w");

   foreach (i; 0 .. 2600) {
       dosya.writeln(`<!print("asdqwewq")!>`);
   }
}

Komut[] oku(string dosyaİsmi)
{
   Komut[] komutlar;
   auto dosya = File(dosyaİsmi, "r");

   foreach (satır; dosya.byLine) {
       komutlar ~= tara(satır.idup);  // Buradaki .idup çok önemli çünkü
                                      // byLines hep kendi içindeki bir
                                      // satırı kullanır.
   }

   return komutlar;
}

void main()
{
   auto dosyaİsmi = "print_komutu_deneme_dosyasi";
   yaz(dosyaİsmi);
   Komut[] komutlar = oku(dosyaİsmi);
   foreach (komut; komutlar) {
       komut.işlet();
   }
}

'$ time ./deneme > /dev/null

real 0m0.015s
user 0m0.004s
sys 0m0.010s
'

Ali

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

November 01, 2012

Alıntı (acehreli):

>

Doğrusu ben Variant'ın da doğru çözüm olduğundan emin değilim. Salih'e sorduğum soru hâlâ geçerli: Dosyadan taradık ve bir dizi Variant edindik diyelim. Daha sonra bunlarle ne yapabiliriz? Nereden bilebiliriz her Variant'ın içinde hangi asıl tür var?

Ben de bu yüzden Variant sınıfını kullanmadan klasik bir şekilde Interface (aslında abstract class öyle değil mi hocam?) kullanarak çözmeye çalıştım. Bunu yaklaşık 24 saattir yapıyorum...:)

Düşünün, dünden beri dışarıda, yemek yerken, yürürken ve hatta uykumda çözmeye çalışıyorum. Adeta kaput oldum çünkü türü arayüze versen bir türlü vermesem bir türlü! Çünkü interface türden bağımsız olması gerekiyor. Örneğin:

 interface Foo(T) { ref T opCall(); }

 class Bar(T) : Foo!T {
   T x;

   this(T x) {
     this.x = x;
   }

   ref T opCall() {
     return x;
   }
 }

 import std.stdio;

void main() {
 Foo!uint[] foo;

 foo ~= new Bar!int(1);
 foo[0]().writeln;
 foo[0]() = 2;
 foo[0]().writeln;

 foo ~= new Bar!uint(1);
}

Yukarıda 'opCall()' ile bir şeyler yapmayı başardım. Gel gör ki ikinci bir tür diziye girdiği zaman işler karışıyor. Bunu ''Foo!'uint'[] foo;'' satırındaki u harfini kaldırarak anlayabilirsiniz. Yani sadece int diye bir tür varsa ve biz uint'i türünde bir nesne eklersek doğal olarak son satıra hata atıyor. Bu sefer int'e çevirsek yukarıdaki satırlara uymuyor ve hata veriyor.

Bunun mutlaka çözümü vardır. Bakalım ilk kim bulacak...:)

Ama dilin geliştiricileri yeni sürüme basit bir özellik ekleyerek harikalar yapabilir. Yoksa D hack yapmamız icap ediyor ya da işaretçiler (pointers) ile kafayı yiyeceğiz. Bir yol daha aklıma geliyor ki o da türün işaretini ve boyutunu (sizeof) yapıya yazıp başka bir sınıf ile sarma yapma. Şu an onun üzerine çalışıyorum. Gelişme olursa yazarım.

Başarılar...

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

November 01, 2012

Alıntı (acehreli):

>

Alıntı (Salih Dinçer):

>

Bunun mutlaka çözümü vardır. Bakalım ilk kim bulacak...:)

OOP kullanan binlerce programcı biliyor zaten. :)
Kim onlar...:)

Bu arada ilginç şeyler keşfettim! Ben değil, D'ciler, std.typecons modülünde harika ciciler yapmış:

import std.stdio, std.typecons, std.string;

       interface I { ref int opCall(); }
       static class A
       {
           public:
             size_t id = 1;

           abstract :
             ref int opCall();
             override string toString();
       }

       static class Foo: A, I {
         int t;
         this(int x) { t = x; }
         //ref int opCall() { return t; };
         //override  string toString() { return t.format; }
       }


       I[] test;
       {
           test ~= new BlackHole!Foo(10);
           test[0]()++;
           test[0]().writeln;

           test ~= new BlackHole!Foo(20);
           test[1]()++;
           test[1]().writeln;

           test ~= new BlackHole!Foo(30);
           test[2]()++;
           test[2]().writeln;
       }
           test.writeln;

Şimdi bunun ne esprisi var diyebilirsiniz. Olay tamamen soyutlama (abstract) ile ilgili. Yani interface ile yetinmiyoruz bir de A isminde başka bir sınıf (bunu "static abstract class A" şeklinde de yazabilirdik!) ile soyut üyeleri parmağımızda oynatıyoruz. Bunu da BlackHole ismindeki şablonla yapıyoruz. Normalde o olmadan hata alıyoruz; isterseniz deneyin...:)

En iyisi mi fasülyenin faydasına (esprisine) geçelim. Biliyorsunuz sınıflar içinde bir toString işlevi vardır ama biz göremeyiz. Ne işe yarıyorsa artık. Mecburen işe yarasın diye override yaparız. Çünkü bizim üyelerimizi bilemiyor...:(

Neyse, ister tanımlı isterseniz tanımsız (hiç bir yerde kaşılığı) olmayan soyut üyeler tanımlayabiliyoruz. Eğer tanımlıysa ve siz bunu somut sınıfta karşılığını vermezseniz (örneğin yukarıdaki gibi toString satırını gizledim), bu soyut üye tanımlıyı bastırıyor. İşin bir güzeli de tıpkı interface'de olduğu gibi bir karşılığının akrabalarında (child) olması şart değil; yani:

Siz, eğer interface'de bir üye tanımlarsanız kalıtım yoluyla bunun bir karşılığını tanımlamanız gerekiyor. Abstract ile buna gerek yok. Bunu ise opCall işlevinin gizlendiğinden anlayabilirsiniz. Tabi soyut sınıfımız olan A'dakini de kaldırırsak interface ötmeye başlıyor, hani bana, hani bana diye...:)

Bir ilginç yanı da opCall'ın bir karşlığı olmadığı halde, soyut olan sınıf sayesinde statik bir şekilde somutlaştırılması. Çünkü yukarıdaki örneğin çıktısı '"1\n2\n3\n"' şeklinde. Bütün gizli satırları açarsanız da her şey düzgün çalışıyor.

Başka bir ilginç yan ise soyut olan sınıf içine somut bir public değer koyabilmem! Aslında A sınıfı, görünüşte sadece static bir sınıfmış gibi. Ama dedim ya abstract takısını da kullanabilirsiniz; bir fark yok. Aynı şekilde soyut değer de kullanabiliyorsunuz. Yani ilginç bir şekilde soyut ile somut üyeler bir arada. Hatta bu sınıfı tek başına da kullanabiliyorsunuz. Ben biraz renk katayım istedim.

:D

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

November 01, 2012

Alıntı (Salih Dinçer):

>

Bunun mutlaka çözümü vardır. Bakalım ilk kim bulacak...:)

OOP kullanan binlerce programcı biliyor zaten. :)

Alıntı:

>

Ama dilin geliştiricileri yeni sürüme basit bir özellik ekleyerek

Önce mevcut olanakların yetersiz olduğunu ispatlamak gerek.

Burada yanıtlanması gereken şu: Bu nesnelerin toplu olarak türleri nedir ve bunlarla ne yapılır? Örneğin Kedi ve Köpek Hayvan'dır ve bütün Hayvan'lar sesÇıkart()'ır, beslen()'ir, vs. Veya program başka ne istiyorsa onu yapar.

Yani dosyadan taranan her veri "her türden" olamaz. Bir anlamı olmak zorundadır.

Ali

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

November 01, 2012

Bu kadar mı! Belki de bu en anlamsız (abstract ~ soyut) olanıydı. Elimden geldiğince anlamdırmaya çalışmıştım ama şu Proxy mixin şablonuna ne demeli; ihtiyacınız olan her şeyi koyuyor oraya...:)

static struct tamSayı(T) { // byte, char, short hariç!
 private T value;
 mixin Proxy!value;
 this(T n){ value = n; }
}
 tamSayı!int s = 50;
 s >>= 1; // s = 25;
 s++; // s = 26;
 s /= 2; //s = 13;

Orijinalinde (https://github.com/D-Programming-Language/phobos/blob/master/std/typecons.d#L2717) sadece int verilmiş ve test edilmiş. Ancak bir kusuru var; tüm kesirli türlerde çalışmazken int ve long'da çalışıyor...

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

November 01, 2012

Yaklaşık 30 iletinden sonra...

Artık konunun cevabını vereyim. Belki gelecekte birileri araştırdığında işine yarayacak. Ancak bu Zekeriya'nın tam olarak istediği değil sanırım. Öyle değil mi?

Maalesef farklı türler konusunda çok zorlandım. Belki önceki sayfada verdiğim çözüm ile tek tür (string) olarak ekrana yazabiliyoruz ama bunlar yönetmede (data management) başarılı olamadım. Belki de format() işlevi yerine bir şey koyarsak olabilir. Çünkü ekrana yansıyan veriler onun gözetmenliğinde geçiyordu. Neyse soruya gelelim:

Dizi içinde dizi kullanımı nasıl?

class içİçeDizi(T) {
   union {
     T     x; // tek değerli herhangi bir tür
     T[]   y; // tek boyutlu herhangi bir tür
     T[][] z; // iki boyutlu herhangi bir tür
   }
   T opIndex(T t) {
     x = t;
     return x;
   }
   T[] opIndex(T[] t...) {
     y = t;
     return y;
   }
   T[][] opIndex(T[][] t...) {
     z = t;
     return z;
   }
 }

 import std.stdio;
 alias size_t Tür;

void main() {
 içİçeDizi!Tür[3] dizi = new içİçeDizi!Tür; {
   "[".write;
   dizi[0][1].write(", ");
   dizi[1][1, 2].write(", ");
   dizi[2][[1, 2, 3], [3, 2, 1]].writeln("]");
 }
}// Çıktısı: [1, [1, 2], [[1, 2, 3], [3, 2, 1]]]

Dediğim gibi, yukarıdaki koddan da anlaşılacak; aynı dizide farklı türler konusunda başarılı olamıyoruz. Belki bu konu OOP'un da üzerinde çünkü programlama dünyasının gerçekleri (türler ve birbirine dönüşümler!) yüzünden kısıtlanıyoruz. Elbette Python'da bir programlama dili ama zannedersem her şeyi tek bir tür olarak niteliyor. Bu ise yüksek bellek ihtiyacı ve yavaşlık olarak bizden bazı bedeller almasına neden oluyor.

Başka çözümü olan var mı?
**
Dip Not:** '[1, [1, 2], [[1, 2, 3], [3, 2, 1]]]' böyle bir sonucu elbette çok boyutlu bir diziyle alabilirdik ama her elemanın bellekte kaplayacağı alan en büyük elemanın içindeki dizinin elemanları kadar olacaktı.

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

November 02, 2012

Alıntı (acehreli):

>

İndeksin değer olarak kullanılması da ilginç olmuş. Olası yanlışlıkları gizleyecektir ama belki yararlı kullanımları da vardır.
Yaptığımız iş diziler ile ilgili olduğu için opIndex() kullandım, yoksa aşağıdaki gibi opCall() kullanılırsa köşeli parantezler yerine işlevlerde olduğu gibi parantezli veri girişi yapılabiliyor. Ancak bu da bana garip görünüyor çünkü o bir işlev değil!

 class içİçeDizi(T) {
   union {
     T     x; // tek değerli herhangi bir tür
     T[]   y; // tek boyutlu herhangi bir tür
     T[][] z; // iki boyutlu herhangi bir tür
   }
   T opCall(T t) {
     x = t;
     return x;
   }
   T[] opCall(T[] t...) {
     y = t;
     return y;
   }
   T[][] opCall(T[][] t...) {
     z = t;
     return z;
   }
 }

 import std.stdio;
 alias size_t Tür;

void main() {
 içİçeDizi!Tür[3] dizi = new içİçeDizi!Tür; {
   "[".write;
   dizi[0]( 1 ).write(", ");
   dizi[1]( 1, 2 ).write(", ");
   dizi[2]( [1, 2, 3], [3, 2, 1] ).writeln("]");
 }
}// Çıktısı: [1, [1, 2], [[1, 2, 3], [3, 2, 1]]]

Aslında çok daha önemli eksiklikeri var:

Örneğin dolu olan hücreye (elemana) yeni elemanlar ekleyemene. Burada öyle bir şey yok ve hatta hiç parametre girmeyip içeriğini de okuyamıyorsunuz!

Aslında opCall()'ı boş kullanıp bir de ref belirteçi verdiğimizde, artık parametre almadan ve doğrudan değer/dizi gönderek de yapabiliriz. Bu belki hepsinin çözümü olur.

Başarılar...

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