Thread overview
January 20, 2010

Şuan anladıklarım:

  1. Anahtarlı bir biçimde verileri kaydedeceğiz. Örnek veri dosyası:
    -deneme-
    canalpayt
    -den-
    canalpayt

  2. Bunu eşleme tablosuna aktarmak için şöyle bir kod kullanacağız(Bu eşleme tablosu olmadan ki kod.)):
    int veri_oku_eş(out dchar[][] okunanVeri_, dchar[] veriAdı_, dchar[]
    veriYolu_, dchar[] anahtar_)
    {

    dchar[][] okunanVeri__;
    int bulundu = 0;
    string veriAdı_s = to!string(veriAdı_);
    veriAdı = veriAdı_s;///Classa eklenecek
    string veriYolu_s = to!string(veriYolu_);
    veriYolu = veriYolu_s;///Classa eklenecek
    string anahtar_s=to!string(anahtar_);
    anahtar = anahtar_s;///Classa eklenecek
    string dosyaAdı = veriYolu_s~"/"~veriAdı_s~".dkveş";
    string düzgünAnahtar = "*-*"~anahtar_s~"*-*"~"\n";
    File dosya = File(dosyaAdı,"r+");
    while (!dosya.eof()) {
        string satır = dosya.readln();
        if(satır==düzgünAnahtar || bulundu==1){
            if((satır[0..3]=="*-*")&&(satır!=düzgünAnahtar)){
                bulundu=0;
                break;
            }
            dstring satır_sd = to!dstring(satır);
            okunanVeri__~=satır_sd.dup;
        }
    }
    okunanVeri_=okunanVeri__;
    
    return 0;
    

}

  1. Bu kod şu şekilde olacak --anahtar -- sözcüğü okunduğunda eşlemetablosu[anahtar] olacak. Veriler okunduğunda da eşlemetablosu[anahtar]=veri olacak.

Bu eşleme tablosu neye yarayacak ? Bir veri dosyasını eşleme tablosuna aktaracağım ve 1'den fazla anahtarı erişirken daha hızlı erişeceğim.

Bu arada aklıma bir fikir geldi. mixin() sayesinde içinde yazanları derletebiliyorduk değil mi ?
Ben anahtarlı verileri şu şekilde kaydedeceğim(Yani veri dosyası şu olacak):
veri[anahtar]=bilgi;
Bunu dosyadan satır satır okuyup mixin ile derlemeye girmesini isteyeceğim. Bütün dosya otomatik eşlenecek ve ben sadece return veri[anahtar]
diyeceğim o veri döndürülecek. Değil mi ?

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

January 20, 2010

Siz bana nasıl yapacağıma dair bir örnek verebilir misiniz? (Kodlarla verirseniz iyi olur. Çünkü ben birbirimizi anlamadığımızı düşünüyorum.)

Bu arada mixin hakkında dedikleriniz doğru.(Ben yorumlamalı dillerle karıştırdım. )

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

January 20, 2010

Tamam teşekkür ederim her şey anlaşıldı.

Şimdi sizin yazdığınız gibi işlevi kullanırsam eşleme tablosu hiç bir işe yaramıyor. Çünkü işlevi çağırdıkça işlev en baştan başlıyor.
En baştan başlatmaması için şöyle kodlamamız gerekiyor(Böylece 2.kere aynı veriyi okuyacaksa tanımlı olduğunu anlıyor ve 2.si çok daha hızlı çalışıyor.):

import std.cstream;
import std.stream;
import std.random;
import std.date;

void rastgele_yaz(string dosya_ismi)
{
   auto dosya = new File(dosya_ismi, FileMode.OutNew);

   foreach (i; 0 .. 100000) {
       dosya.writefln("anahtar", i);
       dosya.writefln(uniform(0, 1000));  // rastgele veri
   }
}

string[string][string] oku(string dosya_ismi)
{

   string[string][string] veriler;
   if(veriler.length<1){
       auto dosya = new File(dosya_ismi, FileMode.In);

       while (!dosya.eof()) {
           char[] anahtar = dosya.readLine();

           if (dosya.eof()) {
               throw new Exception(("Dosya düzeni hatası: "
                                    ~ anahtar ~ " için veri bulunamadı").idup);
           }

           char[] veri = dosya.readLine();
           veriler[dosya_ismi][anahtar] = veri.idup;
       }
   }
   return veriler;
}

void main()
{
   string dosya_ismi = "deneme.txt";
   rastgele_yaz(dosya_ismi);
   void deneme(){
   string[string][string] veriler = oku(dosya_ismi);}
   void deneme2(){
   string[string][string] verileri = oku(dosya_ismi);
}
   dout.writefln("birinci: ", benchmark!(deneme)(1));
   dout.writefln("ikinci: ", benchmark!(deneme2)(1));

}


benchmark şablonunun verdiği sürelere inanmayın. İlki 1 dakika sürüyor hemen hemen 2.si 2 saniye filan. Ama benchmark'a göre 2side aynı hızda hemen hemen.

Ama şöyle bir sorun var gibi. Eşleme tablosuna aktardığımız zaman dosyaya yeni bir bilgi eklendiyse ne olacak. Sanırım bu durumda eski hali kalacak.

Ve yine ama bu kadar yüksek hız için o kadarcık külfet çekilir.

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

January 20, 2010

Alıntı:

>

mixin() sayesinde içinde yazanları derletebiliyorduk değil mi ?
Ben anahtarlı verileri şu şekilde kaydedeceğim(Yani veri dosyası şu olacak):
veri[anahtar]=bilgi;
Bunu dosyadan satır satır okuyup mixin ile derlemeye girmesini isteyeceğim. Bütün dosya otomatik eşlenecek ve ben sadece return veri[anahtar]
diyeceğim o veri döndürülecek. Değil mi ?

Güzel bir fikir ama ancak verinin durağan olduğu programlarda işe yarar.

Bir oyun programının rekor listesini kaydetmek için kullandığı bir durumda, programı her başlatmadan önce derlemek gerekir. D çok hızlı derleniyor ama yine de garip. :)

Ali

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

January 20, 2010

Sen soru cümlerinden sonra cevap da verince, ben sesli olarak düşünüyorsun ve neyi anlamış olduğunu söylüyorsun sanıyorum. Doğru olunca da cevap yazmanın gerektiğini düşünmüyorum. :)

Şu program bir eşleme tablosuna okuyor:

import std.cstream;
import std.stream;
import std.random;

void rastgele_yaz(string dosya_ismi)
{
   auto dosya = new File(dosya_ismi, FileMode.OutNew);

   foreach (i; 0 .. 10) {
       dosya.writefln("anahtar", i);
       dosya.writefln(uniform(0, 1000));  // rastgele veri
   }
}

string[string] oku(string dosya_ismi)
{
   string[string] veriler;

   auto dosya = new File(dosya_ismi, FileMode.In);

   while (!dosya.eof()) {
       char[] anahtar = dosya.readLine();

       if (dosya.eof()) {
           throw new Exception(("Dosya düzeni hatası: "
                                ~ anahtar ~ " için veri bulunamadı").idup);
       }

       char[] veri = dosya.readLine();
       veriler[anahtar] = veri.idup;
   }

   return veriler;
}

void main()
{
   string dosya_ismi = "deneme.txt";
   rastgele_yaz(dosya_ismi);
   string[string] veriler = oku(dosya_ismi);

   foreach (anahtar, veri; veriler) {
       dout.writefln(anahtar, ": ", veri);
   }
}

Eşleme tablosundan dosyaya yazmak da main'in sonunda dout'a yazdırmakla aynı olur. Aynı olsun diye ben stream.File'ı kullanmayı seviyorum.

Ali

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

January 21, 2010

Alıntı:

>
string[string][string] oku(string dosya_ismi)
{

    string[string][string] veriler;

O yerel bir değişken değil mi? Yaşamına o noktada ve boş olarak başlar.

Amacımız neydi ? Benim bildiğim kadarıyla eşleme tablosuna çağırıp oradan okutacağız. Böylece birden fazla kere çağrıldığında hız kazancı yaşayacağız.(Yani bunu yazmamdaki amaç daha önce okunup eşleme tablosuna aktarıldıysa yine aktarılmasın aktarılan eşleme tablosundan direk sonuca dönsün diyeyazdım.)

Alıntı:

>
 if(veriler.length<1){

Hiç veriler.length'in >=1 olduğu durumla karşılaştın mı? Eğer öyleyse dmd bozuk demektir. ;)

Ben karşılaştım. Aynı işlevi 2.kez çağırdığımda zaten daha önceden tanımlı ve veriler aktarılmıştı.(Bence verilere bilgi aktarıldıktan sonra programın sonuna kadar o bilgileri tutması normal. Ne dmd'nin ne de benim hatam. ;-) Sadece verdiğim kodları derleyin ve kendiniz süre tutun. Ne demek istediğimi anlayacaksınız. ) O yüzden tekrar aktarılmadı.
Keşke derleyip çalıştırsaydınız, ne demek istediğimi anlardınız.

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

January 20, 2010

Alıntı (canalpay):

>

Şimdi sizin yazdığınız gibi işlevi kullanırsam eşleme tablosu hiç bir işe yaramıyor. Çünkü işlevi çağırdıkça işlev en baştan başlıyor.

Ben o işlevi bir dosyadan bir eşleme tablosuna nasıl okunacağını göstermek için yazdım. Bu soruyu sorduğunu düşündüğüm için... :)

Oysa şu kadar basit, değil mi:

//dosyadan okuduktan sonra
veriler[anahtar] = veri;

Doğrusu, o işlevi biraz da utanarak yazdım. :)

O işlevi her seferinde çağırmak istemedim. Yalnızca baştan, bir kere, çağrılacak ve bütün dosya belleğe alınacak. Ondan sonra bütün işlemler bellekte, bu veri tabanı ile yapılacak. Bir kere okunacak. php'cilerin istedikleri gibi... ;)

Eşleme tablosu, dkv'nin içindeki bir Tablo sınıfının üyesi olabilir (derlemeden):

class Tablo
{
   string[string] veriler;   // buna anahtarla erişilebilir
}

class dkv
{
   Tablo[string] tablolar;   // buna tablo ismiyle erişilebilir (dosya ismi
                             // fazla kullanışsız olabilir)
}

// Sonra dkv veriyi şöyle sunabilir:
string veri_oku(string tablo_ismi, string anahtar)
{
   return tablolar[tablo_ismi][anahtar];
}

// Veya kullanıcılar Tablo'yu doğrudan kullanabilirler:
Tablo tablo = benim_dkv.tabloya_eriş("benim-tablom");
string veri = tablo.veri_oku("benim-anahtarım");

Alıntı:

>
> string[string][string] oku(string dosya_ismi)
> {
>
>     string[string][string] veriler;
> ```


O yerel bir değişken değil mi? Yaşamına o noktada ve *boş* olarak başlar.

main içindeki 'veriler' ile bunun bir ilgisi yok değil mi?

Alıntı:
>
>
if(veriler.length<1){

Hiç veriler.length'in >=1 olduğu durumla karşılaştın mı? Eğer öyleyse dmd bozuk demektir. ;)

Alıntı:

>

Eşleme tablosuna aktardığımız zaman dosyaya yeni bir bilgi eklendiyse ne olacak.

Öncelikle: Senin tasarımını böyle bozduğum için kusura bakma. Öyle yapmak zorunda değilsin tabii ki. Seninki de çalışır. Ben yalnızca yavaş olabileceğini söylemek istedim.

Yanıt: Bütün işlemler bellekte yapılacak. Dosyaya yalnızca özellikle kaydet() dendiğinde, veya bu nesnenin sonlandırıcı işlevinde yazılacak.

Ama bu, benim kafamda canlandırdığım. Öyle yapmak zorunda değilsin. Bence önceki tasarımına dön, bu sınıf öyle kullanılsın ve varsa sorunlar yaşanarak görülsün. Eğer sorun yoksa, yoktur zaten... :)

Alıntı:

>

Sanırım bu durumda eski hali kalacak.

Ve yine ama bu kadar yüksek hız için o kadarcık külfet çekilir.

Ona külfet değil, veri kaybı denir. :) Tabii ki kabul edilmez.

Ali

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

January 21, 2010

Tamamen siz haklısınız. Ben yapmak istediğim ile yaptığım şeyler ne yazıkki aynı değil.

Ama onu şu şekilde yaptığımı düşünün:

import std.cstream;
import std.stream;
import std.random;
import std.date;
string[string][string] veriler;
void rastgele_yaz(string dosya_ismi)
{
   auto dosya = new File(dosya_ismi, FileMode.OutNew);

   foreach (i; 0 .. 100000) {
       dosya.writefln("anahtar", i);
       dosya.writefln(uniform(0, 1000));  // rastgele veri
   }
}

string[string][string] oku(string dosya_ismi)
{


   if(veriler.length<1){
       auto dosya = new File(dosya_ismi, FileMode.In);

       while (!dosya.eof()) {
           char[] anahtar = dosya.readLine();

           if (dosya.eof()) {
               throw new Exception(("Dosya düzeni hatası: "
                                    ~ anahtar ~ " için veri bulunamadı").idup);
           }

           char[] veri = dosya.readLine();
           veriler[dosya_ismi][anahtar] = veri.idup;
       }
   }
   return veriler;
}

void main()
{
   string dosya_ismi = "deneme.txt";
   rastgele_yaz(dosya_ismi);
   void deneme(){
   string[string][string] veriler = oku(dosya_ismi);}
   void deneme2(){
   string[string][string] verileri = oku(dosya_ismi);
}
   dout.writefln("birinci: ", benchmark!(deneme)(1));
   dout.writefln("ikinci: ", benchmark!(deneme2)(1));

}

Bu yapmak istediğime daha yakın sanırım. Birde siz deneyin.

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

January 21, 2010

Alıntı (canalpay):

>

Alıntı:

>
string[string][string] oku(string dosya_ismi)
{

    string[string][string] veriler;

O yerel bir değişken değil mi? Yaşamına o noktada ve boş olarak başlar.

Evet, o yerel bir değişken olduğu için; o noktada ve boş olarak oluşturulur.

Alıntı:

>

Amacımız neydi ? Benim bildiğim kadarıyla eşleme tablosuna çağırıp oradan okutacağız.

Diğer tarafta da söylediğim gibi, ben baştan her bir tek veri için dosyayı açıp okuyorsun diye düşünmüştüm. O yüzden başından beri buna karşı çıkıyordum. Ama yanılmışım.

Ama, yukarıdaki oku işlevinde hiçbir kazancın olmuyor. İşlev her çağrıldığında yerel olduğu için, veriler diye yeni bir eşleme tablosu oluşturuluyor.

Alıntı:

>

Böylece birden fazla kere çağrıldığında hız kazancı yaşayacağız.(Yani bunu yazmamdaki amaç daha önce okunup eşleme tablosuna aktarıldıysa yine aktarılmasın aktarılan eşleme tablosundan direk sonuca dönsün diyeyazdım.)

Yukarıdaki denetim hiçbir kazanç sağlamaz. length her zaman için 0'dır.

Alıntı:

>

Alıntı:

>
 if(veriler.length<1){

Hiç veriler.length'in >=1 olduğu durumla karşılaştın mı? Eğer öyleyse dmd bozuk demektir. ;)

Ben karşılaştım.

Dediğim gibi, bir hata olmalı. Ya dmd'de ya da başka bir nedenle öyle gördün.

Alıntı:

>

Aynı işlevi 2.kez çağırdığımda zaten daha önceden tanımlı ve veriler aktarılmıştı.(Bence verilere bilgi aktarıldıktan sonra programın sonuna kadar o bilgileri tutması normal.

'oku' işlevini sen "bir_dosya" ile çağırdın ve veriler okundu. Sonra ben "baska_dosya" ile çağırdım. Senin verilerini mi göreceğimi düşünürsün?

Hem zaten istenmez, hem de öyle olmaz. veriler isimli nesne, yereldir, ve o anda boştur.

Alıntı:

>

Sadece verdiğim kodları derleyin ve kendiniz süre tutun.

Bunu dün de yapmıştım, bugün de yaptım:

$ ./deneme
birinci: [3019]
ikinci: [2983]

Senin sonuçlarına benziyor mu? ;) Performans karşılaştırmalarının yanıltıcılığına hoş geldin! :)

Alıntı:

>

Ne demek istediğimi anlayacaksınız. ) O yüzden tekrar aktarılmadı.

'oku' işlevine girince 'veriler' içinde neler olduğuna bakman açıklayıcı olacak.

Alıntı:

>

Keşke derleyip çalıştırsaydınız, ne demek istediğimi anlardınız.

Yanılmışsın. Dün de bugün de derledim ve denedim. :)

Senin birinci denemenin daha yavaş çıkmasının nedeni, herhalde dış etkenlerledir. Büyük olasılıkla dosya sistemi ile ilgili. Birinci sefer bütün dosya diskten belleğe aktarılıyor ve o yüzden sonraki çağrılar daha şanslı olarak bu giriş çıkış işlemini daha hızlı yaşıyorlar.

Ya da dmd'nin bir bozukluğudur. Ama yerel olan 'veriler' ile ilgili değil.

Ali

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

January 21, 2010

Alıntı (canalpay):

>

string[string][string] veriler;

Anlaştık ama onun bir sınıfın bir üye nesnesi olması gerekiyor. Ya dkv'nin üyesi olmalı, ya da dkv'nin tablolar gibi bir üyesinin üyesi olmalı.

Global değişken kullanmak "mecbur kalmadıkça" yasak! :)

Ali

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