Forum: Ders Arası RSS
Birim testleri hakkında...
Birim testleri hakkında genel bilgiler
zafer #1
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Birim testleri hakkında...
Merhaba,

Birim testler bölümünü yeni bitirdim. Birim testlerin kod ile böyle yakın ve iç içe olması hoşuma gitti. Diğer tarafran çok fazla birim testlerle haşır neşir olmayan birisi olarak yinede diğer dillerde olan testlerin işletilip durumlarının geçerli ve geçersiz diye gösterildiği bir arayüz oluyordu ama sanırım burada böyle bir durum yok. Hatta testin çalışma durumu hiç görülmüyor sanırım, ne zaman hata olursa o vakit ilgili test bize kendisini gösteriyor. Yani diğer test ortamlarındaki gibi tüm testlerin tek tek çalıştırılıp onaylandığı bir görünüm yok sanırım. Bu konuda bilgi verebilir misiniz?

Diğer taraftan öğrendiklerimi pekiştirmek adına küçük bir proje çalışması yapıyorum incelemek isteyen olursa https://github.com/zafer06 adresinden depoma ulaşabilirsiniz. Basit bir telefon rehberi projesi amacım becerebilirsem dersane ile pararalel olarak projeyi iyileştirmek. Öncelikle temel işlemleri yapan kodları yazdım, geçen enum bölümünü okuduktan sonra örnek bir enum kullandım. Şimdide birim testlerini ve ddoc için açıklama metinlerini yazmak istiyorum. Neticede en sonunda sınıflardan oluşan bir yapı ile sona erdireceğim. Sizlerinde öneriniz varsa severek değerlendirebilirim.
https://github.com/zafer06 - depo
acehreli (Moderatör) #2
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ı
zafer:
Birim testlerin kod ile böyle yakın ve iç içe olması hoşuma gitti.

Onu ben de çok yararlı buluyorum. Birim testleri aslında programlama dili ile ilgili bir kavram olarak düşünülmemelidir. O yüzden bir dış araç olması daha mantıklı olabilir. Ama kodun içine yazılabilmesi büyük bir kolaylık olduğu için programcıları yazmaya yöneltiyor.

diğer dillerde olan testlerin işletilip durumlarının geçerli ve geçersiz diye gösterildiği bir arayüz oluyordu ama sanırım burada böyle bir durum yok

Başka dillerde böyle bir olanak olduğundan haberim yok ama evet, bütün ayrı birim testi çatılarında öyle olanaklar var. Örneğin bizim C++ için kullandığımız UnitTest++ çatısında "şuna eşit mi" diyebiliyoruz:

    CHECK_EQUAL(42, birIslev());

Başka yararlı olanaklar da var. Bu açıdan D'de dilin içindeki birim testleri oldukça yetersiz kalıyor. O yüzden bir kaç tane birim testi çatısı projesi görmüştüm ama fazla ilgilenmedim. Hatta D1 zamanında kalmış bile olabilirler.

Hatta testin çalışma durumu hiç görülmüyor sanırım, ne zaman hata olursa o vakit ilgili test bize kendisini gösteriyor.

unittest blokları içindeki satırlar aynen kod gibi işletiliyor. writeln() bile yerleştirebiliyoruz ve çıktısını görebiliyoruz. assert()'in patlaması ile de sonlanıyor. :-/ Evet, çok yararlı ama olanakları çok daha fazla olabilirmiş.

incelemek isteyen olursa https://github.com/zafer06

Çok güzel! :)

Sırf birşeyler söylemiş olmak için:

  • Türkçe harfler eksik ;) Kod nasıl olsa Türkçe olduğu için yabancılar anlayabilsin diye bir kaygı da yok...

  • ListeTipi'nin değerlerinin başındaki lt'lere gerek yok. C ve C++'ın aksine o isimler zaten her zaman için ListeTipi. olarak yazılmak zorundalar. Yani şöyle de olabilir: ListeTipi.sıralı

  • MenuGoster()'deki 1-5 seçenekleri ile "Seciminiz [1/2/3/4/5]: " dizgisi arasında bir kopukluk var: yeni bir satır eklense iki yere dokunmak gerekir. "[1/2/3/4/5]" bölümünü MenuGoster() kendisi hesaplayıp döndürebilir. Ama şart da değil tabii. :)

Ali
zafer #3
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
Sırf birşeyler söylemiş olmak için:

  • Türkçe harfler eksik ;) Kod nasıl olsa Türkçe olduğu için yabancılar anlayabilsin diye bir kaygı da yok...

  • ListeTipi'nin değerlerinin başındaki lt'lere gerek yok. C ve C++'ın aksine o isimler zaten her zaman için ListeTipi. olarak yazılmak zorundalar. Yani şöyle de olabilir: ListeTipi.sıralı

  • MenuGoster()'deki 1-5 seçenekleri ile "Seciminiz [1/2/3/4/5]: " dizgisi arasında bir kopukluk var: yeni bir satır eklense iki yere dokunmak gerekir. "[1/2/3/4/5]" bölümünü MenuGoster() kendisi hesaplayıp döndürebilir. Ama şart da değil tabii. :)

Ali

Ali lütfen, bütün mesajlarım için birşeyler söylemeyi ihmal etme :)

Yabancılar konusunda bir sorunum yok, bende Türkçe kullanmak istyorum ancak kulladığım editör (http://www.geany.org/) ne yazikki Türkçe karakterli değişken ve metod isimlerini tamamlarken sorun çıkartıyor. Bundan dolayı Türkçe isimleri bu şekilde yazmak durumunda kaldım. Aslında proje bölümünde bir editör projesi vardı ama sanırım bir neticeye ulaşmadı.

ListeTipi konusunda düzeltmeyi yapacağım, hem göze daha hoş görünecek. C, C++ değil ama kullandığım başka dillerden kalan alışkanlık :)

MenuGoster() metodu ile ilgili yazdıkların ilgilimi çekti bu konuyu biraz daha açabilir miyiz? Bu arada bu projede her şey şart amacımız üzüm yemek değil bağcıyı dövmek  :-D
https://github.com/zafer06 - depo
zafer #4
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Tekrar merhaba,

Mesajı yazdıktan sonra MenuGoster() üzerine biraz düşündüm ve şu değişiklikleri yaptım. Bunları yapmak keyifliydi, yeni bir şeyler keşfetmenin tadı bambaşka bişey

int MenuGoster()
{
    string[] menu = [ "===== Telefon Rehberi =====",
                      "Yeni Kayit Ekle.........: 1",
                      "Kayit Duzenle...........: 2",
                      "Kayit Sil...............: 3",
                      "Kayit Listele...........: 4",
                      "Programi Kapat..........: 5" ];
                      
    int secim = 0;
    write(SecimListesiHazirla(menu));
    readf(" %s", &secim);
    
    return secim;
}
 
string SecimListesiHazirla(string[] menu)
{
    string liste = "\n\nSeciminiz [";                    
    foreach (say, satir; menu)
    {
        writeln(satir);
        
        if (say > 0)
        {
            liste ~= (say == menu.length - 1) ? to!string(say) :
                                                to!string(say) ~ "/";
        }
    }
    
    liste ~= "]: ";
    
    return liste;
}

MenuGoster() metodu oldukça temiz ve şık görünüyor ama SecimListesiHazirla()  metodunu daha fazla sade ve güzel hale getiremedim.

kısa .. kısa yazmak istediklerim ...

    • Menü için eşleme tablosuda kullanılabilirdi sanırım ama ben dizilerle biraz daha haşır neşir olmayı seçtim.
    • Seçim işlemini ana bloktan MenuGoster() metodunun içine taşıdım bütünlük anlamında daha iyi oldu gibi ??
    • Seçim satırını ayrı bir metod ile hazırladım. Bu sayede hem MenuGoster() kendi işine odaklandı hem daha kısa bir metod haline geldi, hemde daha temiz oldu.
    • foreach döngüsünü sevdim. Başka dillerde de kullanıyorum ama özellikle topluluk tipine göre elemanı otomatik bilmesi (akıllı) ve tabi ki sayaç değişkeni çok hoşuma gitti. Bu foreach diğerlerini döver :)
    • SecimListesiHazirla() metodunu daha temiz yazamadım yardımlarınızı bekliyorum forum sakinleri...
https://github.com/zafer06 - depo
acehreli (Moderatör) #5
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ı
Tamam, biraz daha kurcalamaya devam edelim. :) Ama tasarım kararların bana çok mantıklı geldi. :)

1) "[1/2/3/4/5]" dizgisini oluştururken 'say' sayacı kullanıldığına göre 'menu' dizisinin sonundaki rakamlar da ondan oluşturulabilir. Hatta eğer menünün genişliği de programcı tarafından belirlenebilse sonuçta programcı yalnızca şunu kullanabilir:

    string[] seçenekler = [ "Yeni Kayit Ekle",
                            "Kayit Duzenle",
                            "Kayit Sil",
                            "Kayit Listele",
                            "Programi Kapat" ];

Ondan sonra belki Menü isminde bir yapı olur:

struct Menü
{
    // ...
 
    this(string başlık, string[] seçenekler)
    {
        // ...
    }
 
    void göster(int genişlik)
    {
        // ...
    }
}

2) Eğer seçenek karakterleri her zaman için 1,2,3... olmayabilecekse, örneğin belirli harfler olacaksa o zaman senin de söylediğin gibi bir eşleme tablosu kullanılabilir. Veya bambaşka bir çözüm düşünülebilir. Seçim karakterleri programcı tarafından verilir ve seçim dizgisi ondan üretilebilir.

3) "[1/2/3/4/5]" değerlerinin "/" ile birleştirilmeleri bana std.algorithm.joiner'ı hatırlattı:

    string[] d = [ "a", "b", "c" ];
    writeln(joiner(d, "/"));

Çıktısı:

a/b/c

Konu konuyu açıyor :) ama joiner gibi aralık algoritmalarını kullanırken onların tembel olduklarını hatırlamakta yarar var. joiner(d, "/") tek başına hiçbir iş yapmıyor. Asıl iş, writeln onu popFront() ile tükettikçe görülüyor. Her ne kadar D.ershane'de çok sonra olsa da aralıklar D'de çok önemli. Henüz yeri olmasa da hatırlatmak istiyorum:

  http://ddili.org/ders/d/araliklar.html

joiner aslında o kadar da kullanışlı değil çünkü onunla int'leri birleştirmeye çalışalım:

    auto d = [ 1, 2, 3 ];
    writeln(joiner(d, "/"));

Aldığımız hataya bakın!

deneme.d(50141): Error: template std.algorithm.joiner(RoR,Separator) if (isInputRange!(RoR) && isInputRange!(ElementType!(RoR)) && isForwardRange!(Separator) && is(ElementType!(Separator) : ElementType!(ElementType!(RoR)))) does not match any function template declaration
deneme.d(50141): Error: template std.algorithm.joiner(RoR,Separator) if (isInputRange!(RoR) && isInputRange!(ElementType!(RoR)) && isForwardRange!(Separator) && is(ElementType!(Separator) : ElementType!(ElementType!(RoR)))) cannot deduce template function from argument types !()(int[],string)


Bu konuda D'ye kızmayın; C++'ta da olduğu gibi, şablon hatalarında derleyicinin yapabileceği fazla bir şey yok. joiner'ı yazanlar parametrelerin uymaları gereken şablon kısıtlamalarını haklı olarak koyuyorlar, derleyici de bizim verdiğimiz int dizisi ile "/" dizgisini birleştiren bir joiner bulamadığını söylüyor. :-/

Burada bir çözüm, d dizisinin elemanlarını to!string'den geçirdikten sonra joiner'a vermektir:

    auto d = [ 1, 2, 3 ];
    writeln(joiner(map!"to!string(a)"(d), "/"));

Bunun daha bir kod gibi görüneni:

    auto d = [ 1, 2, 3 ];
    writeln(joiner(map!q{to!string(a)}(d), "/"));

Konudan bu kadar sapmak yeter. :)

Ali
zafer #6
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
int MenuGoster()
{
    string[] menu = [ "Yeni Kayit Ekle",
                      "Kayit Duzenle",
                      "Kayit Sil",
                      "Kayit Listele",
                      "Programi Kapat" ];
                      
    int secim = 0;
    write(SecimListesiHazirla(menu));
    readf(" %s", &secim);
    
    return secim;
}
 
string SecimListesiHazirla(string[] menu)
{
    string liste = "\n\nSeciminiz [";  
    
    writeln("===== D Telefon Defteri =====");
    foreach (say, satir; menu)
    {
        writeln(satir, " : ", say + 1);
 
        liste ~= (say == menu.length - 1) ? to!string(say + 1) :
                                            to!string(say + 1) ~ "/";
    }
    
    liste ~= "]: ";
    
    return liste;
}

Doğrusunu söylemek gerekirse SecimListesiHazirla() metodu içindeki iki if işlemini bire indirmek için uzun bir süre uğraşmıştım. Kodu bu hale getirdiğimde yukarıda yazdığım gibi iki if'in birinden otomatikman kurtulmuş oldum. (if say > 0) olan if koşulundan bahsediyorum. Bu da gösteriyor ki bazen sorunun çözümü sizin odaklandığınız alanın dışında olabilir (ben sorunun çözümü için döngü içine odaklanmıştım) dolayısıyla sorun için çözüm ararken kodun tamamını görebilmek oldukça önemli. Kodun bu son hali oldukça güzel oldu özellikle string dizisinin görevi olduğu gibi sadece string değerleri tutması en doğru olanı.

joiner()'ı öğrenmem güzel oldu. Ekstra bilgi için teşekkürler ama kullanım adımları içinde henüz tanımadığım işlemlerden dolayı bu bilgiyi şimdilik bir kenara not alıyorum. Sanırım MenuGoster() işlemi şu an için oldukça kullanışlı bir hale geldi. Projeyi geliştirmeye devam ...
https://github.com/zafer06 - depo
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ı
zafer:
Kodun bu son hali oldukça güzel oldu özellikle string dizisinin görevi olduğu gibi sadece string değerleri tutması en doğru olanı.

Bence de çok güzel. :)

Araları tekrardan nokta karakterleriyle doldurmayı düşünsek string türüyle sorunlar yaşayabiliriz. Şöyle bir işlev yazdım:

import std.stdio;
import std.exception;
import std.array;
 
string[] aralıklıOlarak(string[] soldakiler,
                        string[] sağdakiler,
                        string doldurmaDizgisi,
                        int genişlik)
{
    enforce(soldakiler.length == sağdakiler.length);
 
    string[] sonuç;
 
    foreach (i; 0 .. soldakiler.length) {
        size_t toplamUzunluk = soldakiler[i].length + sağdakiler[i].length;
        string aralık = replicate(doldurmaDizgisi, genişlik - toplamUzunluk);
        sonuç ~=  soldakiler[i] ~ aralık ~ sağdakiler[i];
    }
 
    return sonuç;
}
 
void main()
{
    foreach (satır; aralıklıOlarak([ "bir", "iki", "kırk iki" ],
                                   [ "mor", "mavi", "kırmızı" ], ".", 40)) {
        writeln(satır);
    }
}

string türünde .length karakter adedi anlamına gelmediği için programın çıktısı bozuk oluyor (bütün satırların aynı genişlikte olmalarını istiyoruz):

bir..............................mor
iki..............................mavi
kırk iki.....................kırmızı


.length yerine std.utf.count kullanılınca ise asıl Unicode karakter adedi elde ediliyor:

import std.utf;
 
// ...
 
        size_t toplamUzunluk = count(soldakiler[i]) + count(sağdakiler[i]);

Çıktısı:


bir..............................mor
iki..............................mavi
kırk iki.........................kırmızı


(Not 1: O çıktının sağ tarafı aslında dümdüz. Forum programının azizliği olarak dağınık görünüyor.)

(Not 2: Aslında program yine de hatalı çünkü doldurmaDizgisi'nin uzunluğunu dikkate almıyor. Örneğin "." yerine "-ğ-" gibi bir dizgi kullanılsa hem çıktı düzensiz oluyor hem de genişlik olan 40'ın dışına taşıyor.)

joiner()'ı ... şimdilik bir kenara not alıyorum

Tabii ki. Kendim olanakları değişik ortamlarda tekrar tekrar duyunca öğrenebiliyorum.

Ali
zafer #8
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Eline sağlık Ali çok güzel bir kod olmuş, bahane ile bende bir çok konuyu tekrar etme ve öğrenme fırsatı buldum.

1.string türünde length her zaman karakter adedini vermeyebilir. (Eğer dizginiz ASCII karekterlerden faklı ise)

2.stringin karakter adedini öğrenmek için std.utf kütüphanesindeki count metodunu kullanmak gerekir.

3.size_t'nin türünü öğrenmek için stringof niteliğini kullanmak gerekir. Benim sisteminde size_t uint türünde.

4.enforce exception fırlatır. Exception mekanizması en alt düzeyden yukarı doğru ilerler ve kurulan bir düzenek ile yakalanıp evcilleştirilebilir. assert error fırlatır ve bunun tutulması önerilmez elinizi yakabilir :)

5.stringler immutable char[] davranışı gösterirler karakterlerini değiştiremeyiz ama yeni değerler atayabilir veya başka stringler ekleyebiliriz.

6.replicate (http://www.d-programming-language.org/phobos/std_array.htm…) belirtilen karakterleri belirtilen uzunlukta bir diziye doldurup geri verir. kullanışlı bir metod listeme ekledim.

7.Her nekadar hala dalga(tilda) "~" operatörü ile string eklemeye alışamasamda D de işler böyle. Bence hala "+" daha güzel duruyor. (Not: Ali duymasın şimdi + matematiksel bir operatördür ve toplam amacı ile kullanılır birleştirme olayı saçma diye sinirlenir sonra :))

   size_t toplamUzunluk = count(soldakiler[i]) + count(sağdakiler[i]);

Kodun bu satırını düzenlememe rağmen sağ taraf hizalanmadı bilinçli mi yaptın yoksa beni mi denedin bilmiyorum ama kodu şu hale getirince sonuç düzeldi.

   size_t toplamUzunluk = count(soldakiler[i]);

Hatalı kodda sağ ve sol taraf toplanıyor dolayısıyla 40 birimlik alan içine iki değerde yerleştirildiği için ayarlama yanlış oluyor oysa bizim belirlediğimiz alana sadece sol değer ve noktalar yerleştirilmeli sonrası zaten seçim değeri olacak ve o otomatik hizalanacak.

    foreach (i; 0 .. soldakiler.length)

Ayrıca buradaki length niteliğini string uzunluğu veren length ile karıştırmamak gerekir bu length dizinin uzunluğunu bildirir ve dizilerle kullanımında doğru sonuç verir sanırım?

Son olarak Ali, yazdığın metod için çok teşekkürler ancak senden küçük bir ricam daha olsa eğer vaktin varsa bunu depodaki projeye kendin eklesen böylece bende "pull request" ve "merge" konularında tecrübe edinmiş ve acemiliğimi atmış olurdum ama yoğunum şimdi uğraşamam dersen bende hallederim sorun değil.
https://github.com/zafer06 - depo
acehreli (Moderatör) #9
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ı
zafer:
2.stringin karakter adedini öğrenmek için std.utf kütüphanesindeki count metodunu kullanmak gerekir.

O da ne yazık ki O(N) bir işlem olduğu için biraz yavaştır. Ama öte yandan uzunluğu merak edilen bir dizgi herhalde zaten yine başından sonuna kadar işleneceği için ve o da O(N) bir işlem olduğu için count() ek bir yavaşlık getirmiyordur. (Algoritma karmaşıklıklarında O(N)'ın herhangi katı da O(N) kabul edilir.)

O(1) bir işlem olabilmesi için her dizginin ayrıca karakter uzunluğunu da tutması gerekirdi ve o da dizgilerin uzunluğunu fazla arttırmış olurdu. Ek olarak, dizgiler artık karakter dizisi değil, onları kullanan daha üst bir tür olurlardı.

count()'ı yavaş bulan bir program dizginin uzunluğunu sabit zamanda veren kendi türünü de kullanabilir:

class BenimDizgi
{
    int karakterAdedi;    // <-- artık count()'a gerek yok
    dchar[] karakterler;
    // ...
}

4.enforce exception fırlatır. Exception mekanizması en alt düzeyden yukarı doğru ilerler ve kurulan bir düzenek ile yakalanıp evcilleştirilebilir. assert error fırlatır ve bunun tutulması önerilmez elinizi yakabilir :)

Evet. assert() ve enforce() farkı, geç gündeme gelen ilginç bir konu. D.erhane'de de bir çok yerde işlevlerin giriş koşulları için in bloklarında assert ifadelerinden yararlanılması gerektiği anlatılıyor ama her duruma uygun değildirler.

in blokları sözleşmeli programlamaya (contract programming) uygun. Ancak, sözleşmeli programlama olanakları program -release seçeneği ile derlendiğinde ortadan kalktıkları için, arayüz işlevleri yanlış parametre ile çağrıldıklarını aslında enforce() ile denetlemelidirler. "Arayüz işlevi" derken bir kütüphane işlevini düşünebiliriz.

Basit bir örnek olarak boş olduğunda çağrılmaması gereken bir işleve bakalım:

struct Dizi
{
    int elemanAdedi;
    // ...
 
    bool boş_mu()
    {
        return elemanAdedi == 0;
    }
 
    void elemanSil(/* ... */)
    in
    {
        // YANLIŞ yerdeki denetim
        assert(!boş_mu(), "Boş Dizi'den eleman silinemez");
    }
    body
    {
        // ...
    }
}
 
void main()
{
    auto d = Dizi();
    d.elemanSil(/* ... */);
}

Yukarıdaki programda d.elemanSil() çağrısı -release seçeneği kullanılmadığında patlar; ama -release kullanıldığında tanımsız davranışa yol açar. (in bloğuna güvenen elemanSil() kimbilir hangi bellek bölgelerine dokunmaya çalışır.)

Doğrusu, o denetimin bir enforce() ile ve işlevin içinde yapılmasıdır:

import std.exception;
 
// ...
 
    void elemanSil(/* ... */)
    {
        enforce(!boş_mu(), "Boş Dizi'den eleman silinemez");
 
        // ...
    }

Böylece Dizi.elemanSil() güvenli bir işlev olmaya devam eder.

Eğer kütüphanenin yalnızca kendisinin çağırdığı bir iç işlevden bahsediyorsak, o zaman in bloğu kullanıp kullanmamak programcıya kalmalıdır. Bütün testlerinin tamam olduğunu düşünen programcı programı -release seçeneği ile derleyebilir. İşlevin tek çağıranı kendisi olduğu için de kullanıcılara hatalı olduklarını bildirmek zorunda değildir.

6.replicate (http://www.d-programming-language.org/phobos/std_array.htm…) belirtilen karakterleri belirtilen uzunlukta bir diziye doldurup geri verir.

"Karakterleri" yerine "elemanları" dersek daha genel olur; çünkü her türlü dizi kullanabilir. Bu işi hevesli olarak yapar ve yeni bir dizi döndürür.

Onun uzaktan arkadaşı olan std.range.repeat ise her tür değerle işler ve o değeri tekrarlama işini tembel olarak halleder:

import std.stdio;
import std.range;
 
void main()
{
    writeln(repeat(42, 3));
}

Tekrarlayarak bir aralık oluşturur. Burada önemli olan, sonuçtaki aralık için hiç bellek ayrılmamış olmasıdır (tembelliğin yararı):

[42, 42, 42]

Onlara benzeyen bir de cycle() ve take()'in birlikte kullanımı var. cycle(), hep tekrarlayarak sonsuz bir aralık oluşturur; take() ise o aralıktan belirli sayıda eleman çeker. Yine tembel olarak:

import std.stdio;
import std.range;
 
void main()
{
    writeln(take(cycle("abc"), 5));
}

Çıktısı:

abcab

Not: D keşke şu söz dizimini destekleseymiş istenir ama ne yazık ki henüz öyle bir güzellik yok:

    writeln(cycle("abc").take(5));

7.Her nekadar hala dalga(tilda) "~" operatörü ile string eklemeye alışamasamda D de işler böyle.

Aslında başka dillerden alıştığımız için öyle geliyor. Çünkü toplama ile uç uca ekleme farklı anlamdadırlar.

Bence hala "+" daha güzel duruyor.

Dizgiler dizi olduklarından ve ~ ile +'nın anlamları diziler üzerinde farklı olduğundan karışıklık yaratabilirdi:

    auto dizgi = [ 0, 42 ];
    dizgi[] += 1;
    assert(dizgi == [ 1, 43 ]);

O dizi işlemleri henüz bütün dizi türleri için gerçeklenmiş durumda değil; yeni dmd sürümlerini bekliyoruz...

   size_t toplamUzunluk = count(soldakiler[i]) + count(sağdakiler[i]);

Kodun bu satırını düzenlememe rağmen sağ taraf hizalanmadı

İstediğimi tam olarak açıklayamadım. Sağ tarafın sağ kenarının hizalanmasını istiyordum. Ama kullandığımız forum program yan yana noktaları başka anlama çektiği için doğru olarak gösteremedim bile. Nokta yerine # karakteri ile göstermeye çalışayım:

ğ#######araba
abc####otobüs


    foreach (i; 0 .. soldakiler.length)

Ayrıca buradaki length niteliğini string uzunluğu veren length ile karıştırmamak gerekir bu length dizinin uzunluğunu bildirir ve dizilerle kullanımında doğru sonuç verir sanırım?

Doğru ama string'ler de dizi oldukları için onların tanımını da UTF-8 kod birimi dizisi olarak yapınca yine de dizinin uzunluğunu veriyor. UTF-8 kod birimi ile Unicode karakteri farklı şeyler oldukları için ancak dchar dizgilerinin .length niteliğini bu amaçla kullanabiliriz.

bunu depodaki projeye kendin eklesen böylece bende "pull request" ve "merge" konularında tecrübe edinmiş

Onu yapabilmem için git bilgimi tazelemem de gerekecek. :) Onu sonraya bırakalım.

Ali
zafer #10
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
acehreli:
   size_t toplamUzunluk = count(soldakiler[i]) + count(sağdakiler[i]);

Kodun bu satırını düzenlememe rağmen sağ taraf hizalanmadı

İstediğimi tam olarak açıklayamadım. Sağ tarafın sağ kenarının hizalanmasını istiyordum. Ama kullandığımız forum program yan yana noktaları başka anlama çektiği için doğru olarak gösteremedim bile. Nokta yerine # karakteri ile göstermeye çalışayım:

ğ#######araba
abc####otobüs


Aslında bende forumdaki görüntüden değil kodu projeye eklediğimde oluşan çıktının yanlış olduğundan bahsetmek istemiştim ama neyse önemi yok sorun çözüldü zaten :)

acehreli:
bunu depodaki projeye kendin eklesen böylece bende "pull request" ve "merge" konularında tecrübe edinmiş

Onu yapabilmem için git bilgimi tazelemem de gerekecek. :) Onu sonraya bırakalım.

Olur sorun değil. Projenin bütünlüğünün bozulmaması için ben bu düzenlemeyi yapıp ekleyeyim o zaman.

Ekstra eklediğin bilgiler için çok teşekkürler Ali, bu tür ekstra açıklamaların çok fazla faydasını görüyorum.
https://github.com/zafer06 - depo
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:
Forum: Ders Arası RSS
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, 11:03:31 (UTC -08:00)