Thread overview
A "general" tag
Apr 14, 2012
Xan
Apr 14, 2012
Xan
Apr 16, 2012
Denis Shelomovskij
Apr 16, 2012
Xan
Apr 25, 2012
Marco Leise
April 14, 2012
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.
April 14, 2012
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.
April 14, 2012
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

April 16, 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
April 16, 2012
Uf!, it's more than I can process....
It's really a **complicated** thing to do that in D.

On Monday, 16 April 2012 at 07:50:28 UTC, Denis Shelomovskij
wrote:
> 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.


April 25, 2012
Am Mon, 16 Apr 2012 20:52:16 +0200
schrieb "Xan" <xancorreu@gmail.com>:

> Uf!, it's more than I can process....
> It's really a **complicated** thing to do that in D.

Too much information, yes. Too complicated no. :)
D is statically typed (Fantom allows both static and dynamic typing). That means that for every variable in your program you know beforehand what type it is. You say you have String, Type and Obj. Here we cannot say what type Obj is, because it depends on what Type says. Now you want something from a statically typed language, that it wasn't designed for.

You may want to adapt to the style of a statically typed language and use a struct:

import std.datetime;

struct Person {
	string name;  // a person has a field 'name' of type string
	Date   date;
}

This means that you cannot change the type of 'date' or 'name', and you cannot have a person without a date.

If you really, *really*, REALLY need the full flexibility, you can use Variants. You can store any data in a Variant, so it would replace Type and Obj in your code.

struct Tag {
	string description; // <String>: store "name", "date", etc. in this
	Variant data;       // <Type & Obj>: store "John" or Date(2012, 4, 25) in this
}

Many more solutions are possible, but we'd need to take a look at your code. Also one solution may be more flexible while another is faster. It depends a bit on what you expect. Every language has its pros and cons. Dynamic typing is not one of D's strengths, but execution speed is, for example.

-- 
Marco