May 25

Merhaba,

Ben de çoğunluğa uydum ve artık yabancı foruma bile uğramıyorum! Sanırım ayda bir kafama estikçe. Sahi yapay zeka ile birlikte insanlık böyle sessizleşecek mi acaba :)

Benzer bir konuda (o gün GPT4o ile) şurada bir başlık açmışım. Neredeyse 1 sene olmuş. Claude.AI 4 yayınlanınca yaptığım denemeyi uygulamak istedim. Adeta şok oldum çünkü çok başarılı. İşte sonuç:

import std.stdio;
import std.conv;

struct Stack(T)
{
    private T[] buffer;
    private size_t capacity;
    private size_t head;     // İlk elemanın indeksi
    private size_t tail;     // Sonraki eklenecek elemanın indeksi
    private size_t count;    // Mevcut eleman sayısı

    this(size_t cap)
    {
        capacity = cap;
        buffer = new T[capacity];
        head = 0;
        tail = 0;
        count = 0;
    }

    // Yığıta eleman ekleme
    void push(T item)
    {
        if (count >= capacity)
        {
            writeln("veri kayıt edilmedi, yığıt doldu");
            return;
        }

        buffer[tail] = item;
        tail = (tail + 1) % capacity;
        count++;
    }

    // Yığıttan eleman çıkarma (FIFO - First In, First Out)
    T pop()
    {
        if (empty)
        {
            writeln("döndürülecek bir veri yok, yığıt boş");
            return T.init;
        }

        T item = buffer[head];
        head = (head + 1) % capacity;
        count--;
        return item;
    }

    // Yığıt boş mu kontrolü
    @property bool empty() const
    {
        return count == 0;
    }

    // Yığıt dolu mu kontrolü
    @property bool full() const
    {
        return count >= capacity;
    }

    // Mevcut eleman sayısı
    @property size_t size() const
    {
        return count;
    }

    // Yığıtı temizleme
    void clear()
    {
        head = 0;
        tail = 0;
        count = 0;
    }

    // Yığıtı dizi ile doldurma
    void set(T[] items)
    {
        clear();

        foreach (item; items)
        {
            if (count >= capacity)
                break;

            buffer[tail] = item;
            tail = (tail + 1) % capacity;
            count++;
        }
    }

    // Debug amaçlı - yığıtın mevcut durumunu gösterme
    void printStatus()
    {
        writef("Stack durumu: [");
        if (!empty)
        {
            size_t current = head;
            for (size_t i = 0; i < count; i++)
            {
                writef("%s", buffer[current]);
                if (i < count - 1)
                    writef(", ");
                current = (current + 1) % capacity;
            }
        }
        writefln("] (size: %d/%d)", count, capacity);
    }
}

void main()
{
    writeln("=== D Dilinde FIFO Stack Test ===\n");

    // Integer stack oluşturma
    auto stack = Stack!int(5);

    writeln("1. Boş stack'te pop() testi:");
    int value = stack.pop();
    stack.printStatus();

    writeln("\n2. Stack'e elemanlar ekleme:");
    stack.push(10);
    stack.push(20);
    stack.push(30);
    stack.printStatus();

    writeln("\n3. FIFO test - ilk giren ilk çıkar:");
    writefln("pop(): %d", stack.pop());
    writefln("pop(): %d", stack.pop());
    stack.printStatus();

    writeln("\n4. Yeniden eleman ekleme (circular buffer test):");
    stack.push(40);
    stack.push(50);
    stack.push(60);
    stack.push(70);
    stack.printStatus();

    writeln("\n5. Kapasite aşım testi:");
    stack.push(80); // Bu hata mesajı verecek
    stack.printStatus();

    writeln("\n6. set() metodu testi:");
    stack.set([100, 200, 300, 400, 500]);
    stack.printStatus();

    writeln("\n7. clear() metodu testi:");
    stack.clear();
    stack.printStatus();

    writeln("\n8. String stack testi:");
    auto stringStack = Stack!string(3);
    stringStack.push("birinci");
    stringStack.push("ikinci");
    stringStack.push("üçüncü");
    stringStack.printStatus();

    writefln("String pop(): %s", stringStack.pop());
    stringStack.printStatus();

    writeln("\n9. set() ile fazla eleman testi:");
    stringStack.set(["a", "b", "c", "d", "e"]); // Sadece ilk 3'ü alınacak
    stringStack.printStatus();
}

SDB@79

May 25
Selam,

1) Senin de yazdığın gibi bu bir FIFO. FIFO'yu "stack" olarak adlandırmak herhalde kafa karıştıracaktır. ;)

2) İçinde eleman bulunmayan veri yapısında hata belirtilmeden pop() yapılabilmesi uygun mu? (Çıktıya mesaj yazmak, kodun böyle bir hatayı denetlemesini sağlamaz tabii.)

İlgili olarak, ve tesadüfen bir iş arkadaşımla daha iki gün önce konuştuğumuz gibi, push() ve pop() gibi iki işlev kullanan veri yapısı şüphelidir. Onların yerine şöyle bir üçlü kullanılması doğrudur: push(), top(), ve pop(). (top() yerine head(), first(), vs. gibi daha uygun isim de olabilir.)

Yani, hem eleman kopyalayan hem de veri yapısından o elemanı çıkaran pop() gibi işlevler arayüz (API) tasarımı açısından yanlıştır.

Bu hikayeyi ilk C++'ın "exception safety" anlayışı gelişirken duymuştum. Sorun şu: pop()'un elemanı döndürmeden (tabii aslında "kopyalamadan") önce veri yapısını degiştirmesi gerekir. Orası tamam... Ama eleman kopyalanırken bir hata atılsa, pop()'u çağıran o elemanı göremez ama veri yapısı değişmiştir. Yani, 'catch' ile durumu kurtarmaya çalışsa bile eleman artık yoktur.

Mevcut pop()'ın görev top() ve pop() diye ikiye ayrıldığında o sorun ortadan kalkar.

3) Her ekleme için şurada yapılan denetim gereksiz:

        foreach (item; items)
        {
            if (count >= capacity)
                break;

            // ...
        }

Ve eğer foreach kullanılacaksa neden push() kullanılmamıs?

set() işlevindeki foreach döngüsünün içi aynen push() değil mi? Böyle kod tekrarlarından kaçınmak gerek.

Her ne ise, şu belki push()'tan daha mantıklı olurmuş:

  i) items.length'in doğru olup almadığına bak
  ii) buffer = items yap
  iii) tail ve count'u ayarla

Ali