September 27, 2012

Alıntı (acehreli):

>

O işlevi Türkçe olarak nasıl anlatırsın? Eğer anlatımı basit değilse bir sorun var demektir.
Sanırım tüm sınıfı (artık sınıf oldu...) Türkçeleştirmek gerekirse (-ki bunu düşünüyorum o yüzden "konum" ve "yedek" gibi iki Türkçe ifadeyi koruyorum) 'topBackup()' işlevi yerine 'üsttekiniYedekle()' veya 'sondakiniYedekle()' verebiliriz...

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

September 27, 2012

Kodu dmd 2.060 ile şu değişikliklerle derleyebildim:

   /* [Ali] Sondaki 'const' belirtecine bakılırsa bu işlev bu Stack!T
    * nesnesinde değişiklik yapmayacağı sözünü veriyor. O yüzden 'ref T'
    * döndürmesi olanaksızdır. Döndürebilse, çağıranlar elemanı o referans
    * üzerinden değiştirilebilirler ve böylece işlevin sözü bozulmuş olur.
    *
    * O yüzden bu işlevin 'ref const(T)' döndürmesi gerekir:
    */
   ref const(T) top() const @property
   {
       return stack[konum - 1];
   }

   /* [Ali] Programda top()'ın döndürdüğü referansa gerçekten atama
    * yapılacaksa o zaman bir de const olmayan top gerekiyor. Ne işlev const
    * olmalı, ne de döndürdüğü referans:
    */
   ref T top() @property
   {
       return stack[konum - 1];
   }

   /*** BONUS ***/

   /* [Ali] Bunu şablon olmaktan çıkarttım. Yoksa koddaki 'top=x' gibi
    * kullanımlarda bir üstteki top()'ın mı yoksa bunun mu çağrılacağı
    * karışıyordu.
    *
    * Biraz düşününce mantıklı ama bu şablon olmayınca neden karışmıyor;
    * ondan emin değilim. */
   void top(T value) @property
   {
       stack[konum - 1] = value;
   }

// ...

 /* [Ali] Sondaki noktalı virgülü kaldırdım çünkü:
  *     Warning: use '{ }' for an empty statement, not a ';'
  */
 enum { day = 15, month = 9, year = 2012 }//;

Ali

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

September 27, 2012

Alıntı (Salih Dinçer):

>

Bu durumda sürüm 2.1'e geri dönüyoruz...:)

Sürümlerin öncelikle testlerini geçmeleri gerekmez mi? ;)

Ali

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

September 27, 2012

Alıntı (Salih Dinçer):

>

bir benzeri olan 'first()' işlevine de uyarladığımızda işlev sayısı 2'den 6'ya çıkıyor.

inout anahtar sözcüğü tam da bu sorun için gelmişti. Değişebilen, const, ve immutable yerine geçerek işlev sayısını üçte birine indirir. (Ama gerçekleştirimi hâlâ tam değil).

import std.stdio;

struct Foo(T)
{
   T i;

   ref inout(T) foo() inout
   {
       return i;
   }
}

void main()
{
   auto d = Foo!int();
   const c = Foo!int();
   immutable i = immutable(Foo!int)();

   writeln(typeid(d.foo()));
   writeln(typeid(c.foo()));
   writeln(typeid(i.foo()));
}

Yine de bizim ihtiyacımızı karşılıyor. foo() işlevi üç farklı değişebilme özelliğine sahip Foo!int üzerinde çağrılabiliyor ve uygun türde değer döndürüyor. Çıktısı:

'int
const(int)
immutable(int)'

Alıntı:

>

üçü kullanıldığında da object koda dahil oluyor mu? Sanırım oluyor ve bunu işlevleri farklı isimlendirerek (adreslere yerleştirerek) yapıyor!)

Doğru.

Alıntı:

>

git gide basitlikten uzaklaşıyoruz gibime geldi.

Problem basitlikten uzaklaştıkça kod da basitlikten uzaklaşabilir. D bu konuda benim bildiğim dillerden daha yardımcı. (Andrei'nin sunumlarındaki min() ve max() saydamını hatırlayın (veya bulun). C++'taki onlarca işlev yerine tek işlev yazılabildiğini ve buna rağmen C++'takilerinden daha kullanışlı olduğunu göreceksiniz.)

Alıntı:

>

Hatta espri yoluyla terazi, dünya ve göz misaliyle bir nevi kendimi eleştirdiğim sırada

Eleştiri mi içeriyormuş? :) Bir itirafım var: Ben o tür anlatımlardan hemen hemen hiçbir zaman bir anlam çıkartamıyorum. :blush: Edebi yanımı geliştirmem gerek... :(

Ali

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

September 27, 2012

Sen bir yandan o hatanın kaynağını bulurken ;) ben de unuttuğum bir şeyi söyleyeyim: topBackup()'ı görünce burnuma kötü kokular geldi. :) (http://en.wikipedia.org/wiki/Code_smell).

O işlevi Türkçe olarak nasıl anlatırsın? Eğer anlatımı basit değilse bir sorun var demektir. Tabii ki işlevin içeriğinden bahsetmiyorum. İşlevin işi nedir ve diğer üye işlevlerle bir arada kullanımı nasıldır? Bence basit değil.

Ali

Not: Bu, benim önceki değerli arttırma işlecine (post-increment) olan alerjimle de ilgili. Çünkü onun da tarifi uzundur: değişkenin değerini arttır ama önceki değerini üret. Arttırma işleci ise basittir: değişkeni değerini arttır.

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

September 29, 2012

Çok çok önemli bir düzeltme....:)

   T pop() @property
   {
       auto value = stack[--konum];
       stack.length = konum;
       return value;
   }

Bunu Ali hocamın verdiği, 'üsttekininiYazdır()' örneğini denerken gördüğümüz hata için uygulamalıydık!

Çözümünü ise üretmek için kafa yormadım (hadi artislik olsun; bir kaç saniye düşünsem bulurdum...:)); Robert Sedgewick'in Stack dersinde gördüm. Tabi orada Java kullanıldığı için dizinin uzunluğunu değiştirmeyip null değerine eşitlemiş ama biz D programladığımıza göre çift yönlü çalışan length özelliğini kullanmalıydık...:)

Şimdi içime sine sine, hatta yavaş ve sancılı bir şekilde 2.2 sürümü oluyor gibi. Ancak bir dizi güvenlik düzenlemesi yaparak yığıt3.d'ye geçmeyi düşünüyorum...

Ne dersiniz?

Sürüm 3'de FIFO (ilk giren ilk çıkar) ve LIFO (son giren ilk çıkar) olayına geçmek iyi olmaz mı? Biliyorum; Firefox'un son günlerde yaptığı gibi (herhalde dikkat çekmek için?) sık sık sürüm değiştiriyorum. Öyle ki Linux dünyasında gelenekselleşen bol noktalı ve çok adetli sürüm numaralarına uymuyorum. Ama sonuçta bu basit bir sınıf/yapı öyleyse, gelin birlikte gidelim 7.7'ye...:)

Peki; aç gözlülüğün sınırlarında kalmak kaydıyla...:)

Başka neler ekleyebiliriz? Örneğin yığıtın büyüklüğünü öğrenmek iyi olabilir ki bu basit bir şey. Ama şu FIFO ve LIFO olayını, kurucu işlev tarafından alınacak bir parametre ile yapabilsek bile tek sınıfta zor olsa gerek. Sizce nasıl yapalım? İki farklı sınıf mı? Yoksa tek sınıf içinde bolca düzenlemeye giderek mi?

Teşekkürler...

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

September 29, 2012

Bu yaptıkların harika şeyler ve görüldüğü gibi çok şey öğreniyorsun. :) Umarım "feature creep"in zararlarını da yaşayarak görürsün. ;) (Feature creep, olanakların zamanla yavaş yavaş artması ve türün gittikçe karmaşıklaşmasıdır.)

Stack veri yapısı yeni elemanın üste yerleştirildiği ve eleman erişiminin yalnızca o elemanla yapıldığı bir veri yapısıdır. (Bu arada, stack zaten LIFO'dur ve yapılması gereken de odur.)

Bu tanıma göre C gibi bir dilde yalnızca push() ve pop() olarak yapılabilir. Ama C++ ve D gibi hata düzeneği olan dillerde pop() tehlikelidir. (Bunu daha önce konuşmuştuk.) O yüzden pop()'un yan etkisiz olması gerektiği için bir de top() işlevi gerekir.

Ek olarak, yığıtta eleman bulunup bulunmadığını anlamak için empty() de mantıklı çünkü o yoksa C'deki pop()'ın veya diğerlerindeki top()'ın özel bir değer kullanmaları gerekir. Örneğin elemanların dinamik olmaları şart koşulur ve top() null döndürdüğünde boş anlamına gelebilir. Hoş değil. O yüzden empty() iyidir.

Aslında length() bile şart değildir ama o da başka veri yapılarında var diye eklenebilir. Ancak, C++'a TR1 ile sonradan eklenen tek bağlı listesi forward_list size() içermez! Listenin büyüklüğü böylece küçüldüğünden forward_list hash table uygulamalarında kullanılmaya aday küçük bir veri yapısı haline gelir (daha doğrusu, küçüklüğünü korumuş olur). Bir de uzunluğu olsaydı hash table'ın her gözünün büyüklüğü bir de size_t kadar artardı.

İşte o yüzden length() bile yığıt için seçime bağlı olmalıdır. Bunun nedenlerinden birisi, isteyenlerin (veya senin) o olanağı basitçe ekleyebilmendir:

import std.stdio;

class Yığıt
{
   void foo()
   {
       writeln("foo");
   }

   // ... Yalnızca gerçekten gereken işlevler: push(), top(), pop(), empty()
}

class UzunlukluYığıt
{
   size_t uzunluk;
   Yığıt asılYığıt;

   this()
   {
       asılYığıt = new Yığıt();
   }

   alias asılYığıt this;

   // ... @property olarak length()
}

void main()
{
   auto y = new UzunlukluYığıt();
   y.foo();
}

Böylece yalnızca Yığıt'ın işlevselliğini isteyenler küçük bir tür kullanmış olurlar. Özellikle uzunluk da isteyenler UzunlukluYığıt kullanırlar.

Arayüzleri olabildiğince küçük tutmanın daha yararlı olduğunu göreceksin. :)

Ali

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

September 29, 2012

Ha ha! Tabii ki verdiğim örnek yanlış! :) alias this kullanırsak her pop() ve push() çağrısında uzunluk'u değiştiremeyiz.

Aslında C++'ın std::stack'inin de size()'ı olduğuna göre Yığıt'ta da length() olabilir. Ben yalnızca arayüzün küçük de yapılabileceğini göstermek istedim.

Ali

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

September 30, 2012

Kod örnekli yorumun için teşekkürler hocam...

Sanırım bunu düşünmüştüm. Her ne kadar üretilen object-code olarak çok şey değişmese de bu şekilde miras alma gibi olanaklar kodun kullanımını ve okunmasını sadeleştiriyor. Böylece büyüğen kodun "feature creep" durumuna düşmesi engelleniyor. Ancak ne yaparsak yapalım, sanki "feature creep" olayından uzaklaşamıyoruz. Atomu bile parçalarken karşılaştığımız indirgenemez karmaşıklık hayret vericiyken, elektronlardan oluşan kodlarımızı OOP ile dizgilenmeye çalışıyoruz.

Bu vesileyle herkese tekrar teşekkür etmeliyim...

Çünkü bu foruma üye olduğumdan itibaren OOP hakkında daha çok şey öğrenmeye başladım. Kendime Java'yı seçmiştim ve hatta kolay diye C#'a yönelmiştim. Sonra baktım D'de hazine D.amarı varmış ve kazmamıza bile gerek yokmuş; Ali Çehreli bunu bizim için yapmış...:)

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

January 04, 2013

Yeni bir sürüm ile karşınızdayım!

Tataaaa...:)

Alıntı:

>
> module sdb.ikibinoniki.stacks;
>
> /****************************************************/
>   class Stack(T) {
> /****************************************************/
>     int index;
>     T[] stack;
>                               /* #1: */
>     void push (T data) @property {
>         stack ~= data;
>         this.index++;
>     }
>                               /* #2: */
>     T pop () @property {
>         return stack[--this.index];
>     }
>                               /* #3: */
>     int size () @property {
>         return this.index;
>     }
>                               /* #4: */
>     bool empty () const @property {
>         return this.index == 0;
>     }
> }
> ```


unittest { /* Class Stack Tests */
auto myStack = new Stack!int;
int sum, i = 11;

foreach(data; 0..i) {
myStack.push(data); // #1.
}
assert (i == myStack.size); // #3.

while(!myStack.empty()) { // #4.
sum += myStack.pop(); // #2.
}
assert (sum == 55);

assert (myStack.size == 0);
}

debug void main() {
/* Compile parameters:

  • dmd sdb/ikibinoniki/stacks.d -debug -unittest
    */
    }

Evet, görüldüğü gibi gelişeceğine kırpılmış bir sürümü ile karşılaştınız...:)

Dış görünüş aldatıcı çünkü bu sadece modülün bir parçası. Bu hale dönüşmesine, ne zamandır düşündüğüm derleme çalışması sebep oldu. Baktım; yığıtlar ile ilgili birbirine benzer çok şey yapmışım. Öyleyse, pekala temel bir sınıftan bunları türetebilirdik. Örneğin şurada (<http://ddili.org/forum/thread/1030>) değindiğim yığıt, artık yukarıdaki modülden türemiş olarak şu şekilde kullanılabilir:

import sdb.ikibinoniki.stacks;

//
class BoolStack(T) : Stack!T {
/
/
public:
/***********/
immutable length_t = (T.sizeof * 8);

this (size_t size) {
size_t lenOverflow = size % length_t ? 1 : 0;
super.stack = new T[(size / length_t) + lenOverflow];
}
/* #b1: /
void clear () @property {
foreach(ref cell; stack) {
cell = 0;
}
super.index = 0;
}
/
#b2: */
auto length () const @property {
return (stack.length * T.sizeof) + index.sizeof;
}

private
/***********/
bool bitTest (size_t bit) {
T xCell = stack[bit / length_t];
T xMask = cast(T)1 << bit % length_t;

   return (xCell & xMask) != 0;

}

override:
/***********/
/* #b3: */
void push (T data) @property {
immutable index = super.index / length_t;
immutable xMask = super.index % length_t;

   if(index >= stack.length) {
       throw new Exception("Stack is full!");
   }
   stack[index] |= data << xMask;
   super.index++;

}
/* #b4: /
T pop () @property {
if(!super.index) {
throw new Exception("Stack is empty!");
}
return cast(T)bitTest(--super.index);
}
/
#b5: */
string toString () @property {
string result = "[";
foreach(i; 0..super.index) {
result ~= bitTest(i) ? "1" : "0";
}
return result ~ "]";
}
}

unittest { /* Class BoolStack Tests */
auto data = [ false, true, false, false, true, false, true, true,
true ]; //<-- 2/1 byte ---------------------------^
auto test = new BoolStack!ubyte(data.length);
// 4(int) + 2(ubyte) = 6
assert (test.length == 6 ); // #b2.

assert (test.empty); // #s4.

test.push (false);
assert (!test.empty);

test.push (true);
assert (test.size == 2); // #s3.

test.clear; // #b1.
assert (test.empty);

foreach(d; data) {
test.push(d); // #b3.
}
assert (!test.empty);

assert (test.toString ==
"[010010111]"); // #b5.

foreach_reverse(d; data) {
assert (d == test.pop); // #b4.
}
assert (test.empty);
}


Bir de bu temelden, yeni bir sınıf (örn. RangeStack) türetilip iki aralık işlevi de (popFront(), front() işlevleri) eklenirse, görünürde çok karışmayan/şişmeyen ama aralıklarla da kullanılabilen yeni bir sınıfımız olabilir.

Kolay gelsin...

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