Forum: D Programlama Dili RSS
scope(exit), scope(success), scope(failure)
acehreli (Moderatör) #1
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ı
Konu adı: scope(exit), scope(success), scope(failure)
scope anahtar sözcüğünün bu kullanımına derslerde değinmeyi unutmuşum. :) Az önce tekrar keşfettim.

scope'un bildiğimiz anlamı, "bu nesneyi bu kapsamdan çıkarken sonlandır" demekti:

class Sınıf
{}
 
void main()
{
    foreach (i; 0 .. 10) {
        scope değişken = new Sınıf;
 
    }  // <-- nesne, tam bu noktada sonlandırılır
}

Yukarıda scope yazıldığı için nesne hemen kapsam sonunda sonlandırılır. Yazılmasa, çöp toplayıcı tarafından ilerideki belirsiz bir zamanda sonlandırılır.

Burada ondan söz etmiyorum. scope'un başkaca üç kullanımı daha varmış:

- scope(exit): bu kapsamdan çıkılırken işlet
- scope(success): bu kapsamdan başarıyla çıkılırken işlet
- scope(failure): bu kapsamdan hata ile çıkılırken işlet

import std.stdio;
 
void hataAtabilen(int i)
{
    if (i == 2) {
        throw new Exception("hatalı bir durum");
    }
}
 
void main()
{
    foreach (i; 0 .. 10) {
        scope(exit) writeln("çıkılırken işletilen");
        scope(success) writeln("başarılıyken işletilen");
        scope(failure) writeln("hata durumunda işletilen");
 
        writeln("i: ", i);
        hataAtabilen(i);
    }
}

Çıktısı şöyle:

i: 0
başarılıyken işletilen
çıkılırken işletilen
i: 1
başarılıyken işletilen
çıkılırken işletilen
i: 2
hata durumunda işletilen
çıkılırken işletilen
object.Exception: hatalı bir durum

Mantıklı olarak, scope ifadeleri tanımlandıkları sıranın tersinde işletiliyorlar. (Bunun nedeni, daha aşağıdaki bir scope ifadesinin daha üstteki bir nesneyi kullanıyor olabilmesidir. Temizlik işlevleri ters sırada işletilirlerse, böyle bağımlı kodlar her zaman için doğru çalışır; yoksa, daha aşağıdaki ifadeler sonlanmış nesnelere erişmeye çalışabilirlerdi. Aynı nedenden, bozucu işlevler de ters sırada işletilirler.)

D'deki çoğu olanakta olduğu gibi, scope'lar da blok halinde tanımlanabiliyorlar:

        scope(exit) {
            writeln("çıkılırken işletilen");
            writeln("çıkılırken ayrıca işletilen");
        }

Ali
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ı
scope'ları hatırladığım konuda Walter Bright da scope'un ne kadar yararlı olduğunu gösteren bir örnek verdi.

std.file.read'in D1'deki tanımı:

/********************************************
 * Read file name[], return array of bytes read.
 * Throws:
 *      FileException on error.
 */
 
void[] read(char[] name)
{
    DWORD numread;
    HANDLE h;
 
    if (useWfuncs)
    {
        wchar* namez = std.utf.toUTF16z(name);
        h = CreateFileW(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
    }
    else
    {
        char* namez = toMBSz(name);
        h = CreateFileA(namez,GENERIC_READ,FILE_SHARE_READ,null,OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,cast(HANDLE)null);
    }
 
    if (h == INVALID_HANDLE_VALUE)
        goto err1;
 
    auto size = GetFileSize(h, null);
    if (size == INVALID_FILE_SIZE)
        goto err2;
 
    auto buf = std.gc.malloc(size);
    if (buf)
        std.gc.hasNoPointers(buf.ptr);
 
    if (ReadFile(h,buf.ptr,size,&numread,null) != 1)
        goto err2;
 
    if (numread != size)
        goto err2;
 
    if (!CloseHandle(h))
        goto err;
 
    return buf[0 .. size];
 
err2:
    CloseHandle(h);
err:
    delete buf;
err1:
    throw new FileException(name, GetLastError());
}

Aynı işlevin Alexandrescu'nun scope kullanarak D2'de yazdığı hali:

void[] read(in char[] name, size_t upTo = size_t.max)
{
    alias TypeTuple!(GENERIC_READ,
            FILE_SHARE_READ, (SECURITY_ATTRIBUTES*).init, OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
            HANDLE.init)
        defaults;
    auto h = useWfuncs
        ? CreateFileW(std.utf.toUTF16z(name), defaults)
        : CreateFileA(toMBSz(name), defaults);
 
    cenforce(h != INVALID_HANDLE_VALUE, name);
    scope(exit) cenforce(CloseHandle(h), name);
    auto size = GetFileSize(h, null);
    cenforce(size != INVALID_FILE_SIZE, name);
    size = min(upTo, size);
    auto buf = GC.malloc(size, GC.BlkAttr.NO_SCAN)[0 .. size];
    scope(failure) delete buf;
 
    DWORD numread = void;
    cenforce(ReadFile(h,buf.ptr, size, &numread, null) == 1
            && numread == size, name);
    return buf[0 .. size];
}

Ali
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:
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-19, 08:00:06 (UTC -08:00)