View mode: basic / threaded / horizontal-split · Log in · Help
April 14, 2012
A "general" tag
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
Re: A "general" tag
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
Re: A "general" tag
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
Re: A "general" tag
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
Re: A "general" tag
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
Re: A "general" tag
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
Top | Discussion index | About this forum | D home