January 25, 2012

Ali merhaba, üzülerek söylemek isterim ki kodu yine çalıştıramadım :( Senin yazdığın kodun aynısını kopyaladım ve çalıştırmak istediğimde şu hatayı aldım.

Alıntı:

>

std.conv.ConvOverflowException@std\conv.d(1302): Conversion positive overflow

C:\Users\Zafer\Documents\Projects\Etiket\Etiket\main.d(44): _Dmain

Press any key to continue . . .

Kullandığım sürüm 2.057 ve Windows sistemi üzerinde MonoDevelop ile çalışıyorum. Komut satırı üzerinden derlemeye çalıştığımda aşağıdaki hatayı alıyorum.

Alıntı:

>

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>dmd
DMD32 D Compiler v2.057
Copyright (c) 1999-2011 by Digital Mars written by Walter Bright
Documentation: http://www.digitalmars.com/d/2.0/index.html

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>dmd -w main.d

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>main
std.conv.ConvOverflowException@std\conv.d(1302): Conversion positive overflow

423F30
423DA7
4021BE
403ADC
403B20
403717
4BCBE1

C:\Users\Zafer\Documents\Projects\Etiket\Etiket>

Ayrıca 'scope()' sayesinde Hata Atma ve Yakalama (http://ddili.org/ders/d/hatalar.html) bölümünü tekrar bir gözden geçirdim. Doğrusu çokta iyi oldu hem bilgilerimi tazeledim hemde biraz daha pekiştirdim.

Scope() oldukça kullanışlıymış daha önce dikkat etmeden geçmişim sanırım, try-catch kısmını okuyup devamını atlamışım sanırım. Özellikle bazen try blogunda tanımlı değişkenlere catch veya finally bloklarında ulaşamadığım zamanlarda sorun olurdu ama scope() bu işe gerçekten güzel bir çözüm bulmuş.

Benim o yazıda aklıma takılan sadece scope()'un yaşam alanı oldu. Yani örnekte bir metod verilmiş ve o metodun çıkışında scope() çalıştırılmış ama örneğin o metod içinde iç içe geçmiş yapılar varsa, örnegin if-else veya for döngüsü gibi bunların içindede yaşayıp sonlanan scope tanımları yapılabilir mi?

D dilinde gerçekten güzel ve kullanışlı yapılar var ve bunlarıda güzel bir araya getirmişler, umarım ilgilenen arkadaşlar çoğalır ve D dilini hep beraber daha detaylı irdeleriz.

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

January 25, 2012

Alıntı (zafer):

>

Alıntı:

>

std.conv.ConvOverflowException@std\conv.d(1302): Conversion positive overflow

C:\Users\Zafer\Documents\Projects\Etiket\Etiket\main.d(44): _Dmain

Press any key to continue . . .

conv.d'yi açıp hatanın yerini buldum. O hatayı atan işlevin tamamını kopyalıyorum (bu galiba 2.057'den daha eski ama olsun) :

T toImpl(T, S)(S value)
   if (!isImplicitlyConvertible!(S, T) &&
       (isNumeric!S || isSomeChar!S) &&
       (isNumeric!T || isSomeChar!T))
{
   enum sSmallest = mostNegative!S;
   enum tSmallest = mostNegative!T;
   static if (sSmallest < 0)
   {
       // possible underflow converting from a signed
       static if (tSmallest == 0)
       {
           immutable good = value >= 0;
       }
       else
       {
           static assert(tSmallest < 0);
           immutable good = value >= tSmallest;
       }
       if (!good)
           throw new ConvOverflowException("Conversion negative overflow");
   }
   static if (S.max > T.max)
   {
       // possible overflow
       if (value > T.max)
           throw new ConvOverflowException("Conversion positive overflow");
   }
   return cast(T) value;
}

Yani dönüştürülmekte olan değerin hedef türün en büyük değerinden büyük olduğunu farkediyorlar. Bizim kodda yalnızca to!string var ama stdio.d'nin içine baktığımda seek()'in içinde de to!int(offset) görüyorum. O daha şüpheli çünkü offset bir long. Eğer değeri int.max'tan büyükse sorun oradadır.

Ek: Aşağıda yazdıklarımı unut. -m32 seçeneği ile derleyince ben de hata görüyorum ama başka türlü... Zaman bulunca daha ayrıntılı bakacağım.

~~Hatayı ben yaşamadığım için bu noktada senin tarafında debugging gerekiyor. writeln satırları serpiştirerek hatanın tam olarak hangi işlem sırasında atıldığını yakalayabilir misin.

Rastgele öneri: 'tarz' üyesi tek karakterden oluşuyor ama aslında string'e dönüştürülemez çünkü sonunda '\0' için yer yok. 'tarz' kullanım açısından olsa olsa bir int'tir. Hangi müzik tarzında olduğunu kod olarak saklıyor. Acaba onu mu to!string yapınca oluyor?~~

Alıntı:

>

Benim o yazıda aklıma takılan sadece scope()'un yaşam alanı oldu. Yani örnekte bir metod verilmiş ve o metodun çıkışında scope() çalıştırılmış ama örneğin o metod içinde iç içe geçmiş yapılar varsa, örnegin if-else veya for döngüsü gibi bunların içindede yaşayıp sonlanan scope tanımları yapılabilir mi?

Sonra deneriz ama scope()'un öyle kısıtlamaları olduğundan haberim yok.

Alıntı:

>

D dilinde gerçekten güzel ve kullanışlı yapılar var ve bunlarıda güzel bir araya getirmişler, umarım ilgilenen arkadaşlar çoğalır ve D dilini hep beraber daha detaylı irdeleriz.

Şimdilik bu kadar, :)
Ali

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

January 25, 2012

İşaretli/işaretsiz int konusuna bağlı olan bir programcı (yani Ali :-p) hatası bu. :( .sizeof'un türü size_t (işaretsiz) olduğundan onun eksi işaretlisi de çok büyük bir tamsayı oluyor. Önce işaretli bir tür olan sizediff_t'ye dönüştürünce bende çalıştı:

       dosya.seek(-cast(sizediff_t)ID3v1Pakedi.sizeof, SEEK_END);

Aslında cast(int) de çalışır tabii çünkü ID3v1Pakedi'nin büyüklüğü 128 gibi küçük bir değer.

Ben bunları 64-bitlik dmd ile hem -m32 hem de -m64 ile denedim. Sanıyorum hata oydu; bence Windows'da da çalışacaktır.

Ali

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

January 25, 2012

Alıntı (zafer):

>

Benim o yazıda aklıma takılan sadece scope()'un yaşam alanı oldu. Yani örnekte bir metod verilmiş ve o metodun çıkışında scope() çalıştırılmış ama örneğin o metod içinde iç içe geçmiş yapılar varsa, örnegin if-else veya for döngüsü gibi bunların içindede yaşayıp sonlanan scope tanımları yapılabilir mi?

Soru için teşekkürler. Benim de tekrar etmeme neden oldun. :) scope deyimleri içinde bulundukları en iç kapsamla ilgili. (Bu bilgiyi eklemem gerek.) O yüzden isim alanı karmaşaları da yaşanmıyor.

Şöyle denedim:

import std.stdio;

void foo()
{
   writeln("foo() ilk satır");

   int dış;
   scope (exit) {
       --dış;
       writeln("dış scope(exit): ", dış);
   }
   ++dış;

   if (dış) {
       writeln("if ilk satır");

       int iç;
       scope (exit) {
           --iç;
           writeln("iç scope(exit): ", iç);
       }
       ++iç;

       writeln("if son satır");
   }

   writeln("foo() son satır");
}

void main()
{
   foo();
}

Çıktısı:

'foo() ilk satır
if ilk satır
if son satır
iç scope(exit): 0
foo() son satır
dış scope(exit): 0'

Alıntı:

>

D dilinde gerçekten güzel ve kullanışlı yapılar var ve bunlarıda güzel bir araya getirmişler, umarım ilgilenen arkadaşlar çoğalır ve D dilini hep beraber daha detaylı irdeleriz.

Doğru. scope deyimleri Andrei Alexandrescu'nun özenle hatırlattığı bir konudur. D'nin en yararlı tarafları arasında bir de 'static if'i öne sürer. Tabii bunların ikisi de kendisinin C++ sihirbazlığı yaptığı zamanlarında acı çektiği konulardır. :)

Ali

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

January 25, 2012

Alıntı (acehreli):

>
>         dosya.seek(-cast(sizediff_t)ID3v1Pakedi.sizeof, SEEK_END);
> ```


Bu günlerde çok hata yapıyorum! :( Neden sizediff_t'ye dönüştürülsün ki? seek()'in belgesi 'long' türünde parametre diyor. Doğrusu, long vermektir:


   dosya.seek(-cast(long)ID3v1Pakedi.sizeof, SEEK_END);


Ali

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

Ali bu harika bilgiler için teşekkür ederim. Özellikle scope() örneği çok güzeldi.

Mp3 tag bilgisi kodunu çalıştırmayı başardım ancak aklıma takılan bazı satırlarla ilgili sorularım olacak, bugün işler biraz yoğun, bende soruları bir toparlayıp hazırlardıkça buraya eklerim. Vakit ayırdığın için tekrar teşekkürler.

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

January 27, 2012

Merhaba Ali, kod ile ilgili aklıma takılanları satır satır yazıyoruz. Açıklama getirisen çok sevinirim.

Alıntı:

>

immutable dosyaYeri = dosya.tell(); // <-- değişkende sakla
scope(exit) dosya.seek(dosyaYeri, SEEK_SET);

Bu kodlarla amacımız metotun çıkışında dosyayı ilk haline getirip bırakmak ama buna neden ihtiyaç duyduk
gerçi bu sayde scope()'u tanımış olduk ama işlemin sonunda dosya.close() ile dosyayı kapatmak daha doğru
olmaz mıydı?

Alıntı:

>

ID3v1Pakedi[1] paketler;
dosya.rawRead(paketler);

ID3v1Pakedi paket = paketler[0];

Burada paketler isminde tek elemanlı bir dizi oluşturuyoruz ve rawRead() metoduna bu diziyi gönderiyoruz.
Sonrasında ise dizideki tek elemanı bir pakete aktarıyoruz.Bunun yerine paket isminde bir değşken oluşturup göndersek olmaz mı? Bu belkide rawRead() metodunun arkaplanda fread (http://cplusplus.com/reference/clibrary/cstdio/fread/) metodunu kullanması ile alakalı bir durumudur. (http://www.dlang.org/phobos/std_stdio.html#rawRead)

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

January 27, 2012

Alıntı (zafer):

>
> immutable dosyaYeri = dosya.tell();    // <-- değişkende sakla
> scope(exit) dosya.seek(dosyaYeri, SEEK_SET);
> ```

>
> Bu kodlarla amacımız metotun çıkışında dosyayı ilk haline getirip bırakmak ama buna neden ihtiyaç duyduk
> gerçi bu sayde scope()'u tanımış olduk ama işlemin sonunda dosya.close() ile dosyayı kapatmak daha doğru
> olmaz mıydı?

Bu işlev dosyayı kendisi açmadığı için kapatması da doğru olmazdı.

Tabii işlevi dosyayı kendisi açacak biçimde de tasarlamış olabilirdik. Dosya ismini verirdik, açardı, pakedi okurdu, ve döndürürdü. (Ara not: Ben o zaman bile dosya.close()'u açıkça çağırmazdım. Bir C++ programcısı olarak programları sonlandırıcı işlevler etrafında düşünüyorum. File'ın sonlandırıcısı zaten dosyayı kapattığı için açıkça kapatmaya gerek yok. Açıkça kapatmak, hemen tekrar örneğin başka bir erişim hakkı ile açılacaksa şarttır. Ama açıkça kapatılmasında da hiç sakınca yoktur tabii.)

Ancak, işlevin dosya ismi almasını beğenmemiştim:

* Dosya açmak göreceli olarak masraflıdır. Zaten açık bir dosya varsa onu kullanmak daha etkin olur. (O yüzden de dosyayı baştaki durumuna getirmek için yapmamız gereken tek şey seek()'i çağırmak.)

* Bizi çağıran kodun dosyayı zaten açmış olmasını beklemek mantıklıdır çünkü ID3v1 olup olmadığına ancak dosyanın bazı yerlerini okuyarak karar vermiştir. Yani bizi çağırdığına göre dosyayı açıp içine zaten bakmıştır.

* En önemlisi basitlik. (Basitlik yazılım tasarımlarının en baş ilkesi olmalıdır.) İşlevin şimdiki tanımı şöyle: "dosyanın ID3v1 pakedini okur ve döndürür; paket yasal değilse hata atar." Eğer dosya ismi alsaydı birazcık daha karmaşık olurdu: "dosyayı açar, ... vs. ...". Ama bu sefer dosya açılamadığında da hata atması gerekirdi. Yani işler azıcık da olsa karmaşıklaşmış olurdu. (Bu maddenin o kadar inandırıcı olmadığını kabul ediyorum ama bana File alan işlev daha az karmaşık geliyor. En azından içinde dosya açma satırı yok. :))

Bunlara karşılık senin fikrin de geçerli: dosya ismini alıp dosyayı açıp kapatsak seek() ile baştaki durumuna getirmek gibi bir derdimiz olmazdı. O da kabul. Belki de beni yönlendiren şey gerçekten de dosya açma masrafıydı. Ayrıca işletim sistemleri aynı anda belirli sayıda dosyadan fazlasını açtırmazlar. Zaten açıksa onu kullanmak iyidir.

Alıntı:
>
>
>

ID3v1Pakedi[1] paketler;
dosya.rawRead(paketler);

ID3v1Pakedi paket = paketler[0];

>

Burada paketler isminde tek elemanlı bir dizi oluşturuyoruz ve rawRead() metoduna bu diziyi gönderiyoruz.

Biraz garip yapmışlar: rawRead() şablon olduğu için her tür dizi olarak okuyabiliyor. Ama nedense tek değişkene okuyan yüklemesini yapmamışlar. Onun için tek paket bulunduğunda bile dizi olarak tanımlamak gerekiyor.

Alıntı:

>

Sonrasında ise dizideki tek elemanı bir pakete aktarıyoruz.Bunun yerine paket isminde bir değşken oluşturup göndersek olmaz mı?

Tek değişkene yukarıdaki nedenden okuyamadık. Ama söylediğinin son bölümünü öyle yaptık zaten: paket isminde değişken oluşturup onu gönderdik. Olsa olsa, ondan vazgeçip hep paketler[0]'ı kullanırdık:

       enforce (paketler[0].TAG == "TAG",
                format("'%s', bir ID3v1 dosyası değil!", dosya.name()));

       return paketler[0];

paket değişkenini okunaklılığı arttıracağını düşünerek eklemiştim. Yoksa bir tane olduğunu bildiğimiz pakedi dizi gibi kullanmak garip gelmişti. Ama bunda bir tane kopya eksik olduğu için daha hızlı işleyecektir. (O konuda da derleyiciye güvenmiştim: Derleyici, paket değişkenini gerçekten oluşturmak yerine doğrudan paketler[0]'ı kullanabilir. Tabii bunu programın davranışında bir farklılığa neden olmayacağını kanıtlayabilirse yapar.)

Yapılabilse, daha iyisi şu olurdu:

       alias paketler[0] paket;    // <-- derleme HATASI

O zaman paketler[0]'a paket ismini vermiş olurduk. Ama "bir ifade alias yapılamaz" gibi bir hata mesajıyla derlenemiyor.

Başka bir hayal, paket'in paketler[0]'ın referansı olduğunu belirtmek olurdu:

       ref ID3v1Pakedi paket = paketler[0];    // <-- derleme HATASI

Ama D'de öyle yerel değişken referansları yok. (C++'ta & karakteri ile olabilirdi.) (D'de işlev parametreleri ref olabiliyor.)

Aklıma gelen son yöntem gösterge kullanmak:

       ID3v1Pakedi * paket = &paketler[0];

       enforce (paket.TAG == "TAG",
                format("'%s', bir ID3v1 dosyası değil!", dosya.name()));

       return *paket;

Baştaki paket değişkeninin oluşturulma masrafından kurtulmuş olduk. Bunun gerçekten kazançlı olup olmadığı denenerek bulunabilir.

Ama bence hiçbir program dosyanın sonundan ID3v1 pakedi okuyan işlevin içindeki bir kopya yüzünden yavaşlamaz. Dosya ne de olsa bir işlemde kullanılacaktır. O işlemler yanında 128 baytlık basit bir struct kopyası farkedilmez. :)

Ali

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

January 27, 2012

Ali, kodlar gayet güzel, benim sorumdaki amaç oradaki dizi tanımlama işlemini tam olarak anlamadığımdan dolayıdı yoksa genelde bende senle aynı fikirdeyim. Yalnız üçüncü maddeye farklı bir açıdan bakılabilir.

Alıntı (acehreli):

>
  • En önemlisi basitlik. (Basitlik yazılım tasarımlarının en baş ilkesi olmalıdır.) İşlevin şimdiki tanımı şöyle: "dosyanın ID3v1 pakedini okur ve döndürür; paket yasal değilse hata atar." Eğer dosya ismi alsaydı birazcık daha karmaşık olurdu: "dosyayı açar, ... vs. ...". Ama bu sefer dosya açılamadığında da hata atması gerekirdi. Yani işler azıcık da olsa karmaşıklaşmış olurdu. (Bu maddenin o kadar inandırıcı olmadığını kabul ediyorum ama bana File alan işlev daha az karmaşık geliyor. En azından içinde dosya açma satırı yok. :))

Buradaki basitlik kavramına katılıyorum ve bende yapılan işlemlerin bir arada bulunması açısından belki metodun sadece dosya yolunu alıp dosyayı kendi içinde açıp işlemleri yapmasının daha güzel olabileceğini düşünüyorum. Ancak bu kesinlikle sadece başka bir bakış acısı bir tartışma konusu olacak bir şey değil.

Yardımlar için teşekkürler.

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

1 2
Next ›   Last »