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

Variant türü ile ilgili kitaptada pek kaynak bulamadım. Sadece "Beklenmeyen mesaj almak" başlıklı konuda "her türden veriyi
sarmalayabilen bir türdür
" şeklinde bir açıklama geçiyor.

Benim anladığım kadarıyla diğer dillerde bulunan ve her türlü veriyi taşıyabilen Object türünün bir benzeri, denemek ve tanımak istedim. Aşağıda küçük bir örnek var bir yapıyı (struct) Variant bir değişkene aktardım ancak kendi türünde bir değişkene geri aktaramıyorum?


import std.stdio;
import std.variant;
 
void main()
{
    Klavye q = Klavye("Q klavye");
    Klavye f = Klavye("F klavye");
 
    Variant v = q;
 
    Klavye t = cast(Klavye)v;
 
    writeln(t.adi);
}
 
struct Klavye
{
    string adi;
}

// Hata mesajı
main.d(13): Error: cannot cast expression v of type VariantN!32LU to Klavye because of 
different sizes                                                                                                                                        
shell returned 1
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:
Benim anladığım kadarıyla diğer dillerde bulunan ve her türlü veriyi taşıyabilen Object türünün bir benzeri

Variant, discriminated union denen yapının bir uygulamasıdır. Ben daha önce C++'ta boost::any türüyle kullanmıştım. En basit olarak, bir union'dan ve belirli bir anda o union'ın üyelerinden hangisinin kullanılmakta olduğunu bilen bir enum'dan oluşur. (Bir kaç gün önce öğrendiğim nan-boxing yöntemi enum'a gerek bırakmıyor. Bunun hakkında da yazmak istiyorum ama zaman bulunca... :) )

Variant'ın gerçekleştirmesi kabaca şunun gibidir (burada kolaya kaçarak TypeInfo kullandım; küçük bir enum kullanıldığında daha az yer tutabilir):

import std.format;
import std.exception;
 
struct HerTür
{
    union
    {
        int i;
        double d;
    }
 
    TypeInfo tür;
 
    void yaz(T)(T veri)
    {
        static if (is (T == int)) {
            i = veri;
 
        } else static if (is (T == double)) {
            d = veri;
        }
 
        tür = typeid(T);
    }
 
    T oku(T)()
    {
        if (typeid(T) != tür) {
            throw new Exception(format("%s türündeki veri %s olarak okunamaz"));
        }
 
        static if (is (T == int)) {
            return i;
 
        } else static if (is (T == double)) {
            return d;
        }
    }
}
 
void main()
{
    HerTür ht;
 
    ht.yaz(42);
    assert(ht.oku!int() == 42);
 
    // Aynı değişkene başka tür yerleştiriyoruz:
    ht.yaz(1.5);
    assert(ht.oku!double() == 1.5);
 
    // Yanlış tür olarak okumaya çalıştığımızda hata atılır:
    assertThrown(ht.oku!int);
}
Variant'a bakarken Algebraic'e de bakmak gerek. Yanılmıyorsam daha kullanışlı bir tür...

, denemek ve tanımak istedim. Aşağıda küçük bir örnek var bir yapıyı (struct) Variant bir değişkene aktardım ancak kendi türünde bir değişkene geri aktaramıyorum?

    Klavye t = cast(Klavye)v;

Herhalde güvenli olsun diye DÜZELTME:otomatik elle yapılan dönüşümü engellemiş olmalılar. Variant'ın 'peek' işlevine hangi tür istediğimizi söylemek gerekiyor. Gösterge döndürdüğünden de * işleci:

    Klavye t = *v.peek!Klavye;

Neyse ki == işlecinde otomatik tür dönüşümü var. Şu işliyor:
    assert(v == q);

Ali
acehreli (Moderatör) #3
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ı
Değeri okumak için daha kolayı varmış:
    Klavye t = v.get!Klavye();
Ek olarak, galiba onlar da enum değil, TypeInfo kullanıyorlar.

Ali
zafer #4
Üye Tem 2009 tarihinden beri · 700 mesaj · Konum: Ankara
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Açıklama ve kodlar için teşekkürler çok faydalı oldu. İlk defa gördüğüm ve yabancı gelen TypeInfo ve typeid hakkında biraz daha bilgi verebilir misin? Biraz araştırdım ancak pek bir bilgi bulamadım. Örneğin nerede ve niçin kullanıyorlar?

Ayrıca konuyu daha derinlemesine incelemek isteyenler için anahtar kelimeler: tagged union, variant, variant record, discriminated union, disjoint union, sum type.
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ı
zafer:
TypeInfo ve typeid hakkında biraz daha bilgi verebilir misin?

Ben de dün kitaba eklenmeleri gerektiğini not almıştım. :)

typeid, değeri TypeInfo türünde olan bir ifade:

  http://dlang.org/expression.html#TypeidExpression

TypeInfo, tür ile ilgili ancak çalışma zamanında bilinen bilgi veriyor:

  http://dlang.org/phobos/object.html#.TypeInfo

Ben kitapta getHash() üye işlevini kullanmıştım. getHash, "bu türün eşleme tablosu anahtarını üreten işlevi nedir?" sorusunu yanıtlıyor:

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

Bir kaç gün içinde ekleyeceğim.

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