A "general" tag

Denis Shelomovskij verylonglogin.reg at gmail.com
Mon Apr 16 00:50:24 PDT 2012


15.04.2012 0:31, Xan написал:
> On Saturday, 14 April 2012 at 19:40:06 UTC, Aleksandar Ružičić wrote:
>> On Saturday, 14 April 2012 at 19:17:52 UTC, Xan wrote:
>>> Hi,
>>>
>>> I try to translate a script I wrote in Fantom [www.fantom.org]. In my
>>> script, I have a type "Tag" defined as a triple of:
>>> - String (the name of the tag),
>>> - Type (the type of the tag: could be Str, Date, Int, etc.)
>>> - Obj (the value of the tag; Fantom has Objects of Top-Class hierachy).
>>>
>>> (normally the tag has Type = Obj.Type, but you can manually set).
>>>
>>> For example,
>>> you could have:
>>> (name, Str#, "John")
>>>
>>> or
>>>
>>> (date, Date#, 2011-09-02)
>>>
>>>
>>> (# is the Fantom way for specifying type: Str# is the sys::Str type)
>>>
>>>
>>> Is there any way for emulating this? My main trouble is how to define
>>> Type and Object in D.
>>>
>>> Thanks in advance,
>>> Xan.
>>>
>>> PS: Please, be patient, I'm a newbee.
>>
>>
>> For "Type" look at enum (http://dlang.org/enum.html) and for "Object"
>> look at std.variant (http://dlang.org/phobos/std_variant.html).
>>
>> And since Variant can tell you what type it contains you might no
>> longer need that "Type" parameter.
>
> I think it's not what I expect. Can I have a generic object type?
> Something like an assigment like:
>
> Any a
>
>
> ?
>
> With templates?
>
> Please, guide me. I'm a newbee
>

What you are looking for is a boxing.
http://en.wikipedia.org/wiki/Boxing_(computer_science)#Boxing

D doesn't support auto boxing/unboxing. For a reason see, e.g. this thread:
http://forum.dlang.org/thread/ckoaum$1lbg$1@digitaldaemon.com
http://forum.dlang.org/thread/cr7njl$18j3$1@digitaldaemon.com

There was std.boxer module, but it was deprecated and removed, this is 
the last version before removal:
https://github.com/D-Programming-Language/phobos/blob/c20d454d63861a0c4bab647b37c01b0dd981a3f8/std/boxer.d

std.variant is really what you are looking for. See example:
---
import std.stdio;
import std.variant;
import std.string: format;

struct Tag {
     string name;
     Variant entity;
}

class C {
     int i;

     this(int i) { this.i = i; }

     string toString() { return format("C(i: %s)", i); }
}

struct SmallStruct {
     int a;
}

struct Huge {
     real a, b, c, d, e, f, g;
}

void writeTag(Tag tag) {
     writeln(tag);
     with(tag.entity)
         if(auto intVal = peek!int()) {
             writeln("  Contains int: ", *intVal);
             // Arithmetic is supported too
             writeln("  + 3: ", tag.entity + 3);
             writeln("  * 2: ", tag.entity * 2);
         } else if(auto hugeVal = peek!Huge())
             // Don't use *hugeVal for now, there is a bug in peek
             writeln("  Contains Huge struct: ", tag.entity.get!Huge());
         else if(auto classInfo = cast(TypeInfo_Class)type)
             writefln("  Contains class %s: %s", classInfo.name, 
get!Object());
         else if(auto structInfo = cast(TypeInfo_Struct)type)
             writefln("  Contains struct %s: %s", structInfo.name, 
tag.entity);
         // else if etc.
}

void main() {
     writeTag(Tag("tag1", Variant(12)));
     writeTag(Tag("tag2", Variant("str")));
     writeTag(Tag("tag3", Variant(["str1", "str2"])));
     writeTag(Tag("tag4", Variant(new C(17))));
     writeTag(Tag("tag4", Variant(SmallStruct(3))));
     // Variant isn't enough to hold Huge so a copy
     // will be accocated in GC heap.
     // Yes, this isn't documented yet and `peek` will give you garbage
     // for this case because of a bug.
     writeTag(Tag("tag4", Variant(Huge(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 
7.7))));
}
---

std.variant has some bugs for now but is usable:
http://d.puremagic.com/issues/buglist.cgi?query_format=advanced&short_desc=variant&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&short_desc_type=allwords

Templates are usable in other cases, not this.

-- 
Денис В. Шеломовский
Denis V. Shelomovskij


More information about the Digitalmars-d-learn mailing list