May 10, 2013
On 05/10/13 14:32, deadalnix wrote:
> http://www.deadalnix.me/2013/05/10/type-safe-tagged-union-in-d-programming-language/
> 
> A trick that I used to use more and more, so I ended up creating a generic solution and wrote an article about it.

Nothing 'shameless' about it.

But Real Programmers don't use mixins...

   struct TU(TYPES...) {
      union { TYPES data; }
      ubyte type;
      static assert(TYPES.length<=typeof(type).max);

      T opAssign(T)(T a) {
         foreach(N, TYPE; TYPES)
            static if (is(T==TYPE)) {
               type = N;
               return data[N] = a;
            }
         assert(0);
      }
      this(T)(T a) { this = a; }

      DT as(DT)() @property {
         foreach(N, TYPE; TYPES)
            static if (is(DT==TYPE)) {
               if (type==N)
                  return data[N];
               else
                  assert(0, "Cannot access a '"~typeString(type)~"' as "~DT.stringof);
            }
         assert(0);
      }

      auto ref apply(alias f)() {
         foreach(N, TYPE; TYPES)
            static if (is(typeof(f(data[N])))) // Comment this line out for strict CT checks.
               if (N==type)
                  return f(data[N]);
         assert(0, "Could not apply '"~typeof(f).stringof~"' to "~typeString(type));
      }

      static string typeString()(typeof(type) n) {
         foreach(N, TYPE; TYPES)
            if (N==n)
               return TYPE.stringof;
         assert(0);
      }
   }

   double sqr(double a) { return a*a; }
   int sqr(int a) { return a*a; }

   void main() {
      import std.stdio;
      TU!(int, double, string) u;
      u = 257;
      writeln(u);
      writeln(u.data[0], ", ", u.data[1]);
      writeln(u.as!int);
      //writeln(u.as!double); // RT error
      writeln(u.apply!sqr());
      u = 3.14;
      writeln(u.apply!sqr());
      u = "blah";
      //writeln(u.apply!sqr()); // CT error in 'strict' mode, RT error otherwise.

      // Not currently accepted:
      //writeln(u.apply!(function(a){return a*a;})());
      //writeln(u.apply!(a=>a*a)());
   }

Something that wasn't obvious from your examples is that templates are not necessary when implementing the 'processing' functions - overloading is enough.

The interesting aspect of this is what improvements to the language would help to make this code both a) simpler and more readable, and b) even more efficient. Manual optimizations, such as 'if-sequnences'->'switch', should /not/ result in harder to read code. The locals-can't-be-parms-to-local-templates restriction should only apply when really necessary (for example: static functions/lambdas can be allowed). Etc.

artur
May 10, 2013
On Friday, 10 May 2013 at 14:53:23 UTC, John Colvin wrote:
> On Friday, 10 May 2013 at 13:51:11 UTC, deadalnix wrote:
>>
>> Awesome, I'll update the article.
>>
>
> Andrei pointed out that the title needed fixing:
>
> I suggest:
> Type-safe tagged unions in the D programming language.
> Type-safe tagged unions in D.

I updated everything. Now I need to sleep :D Thank you very much my english if often very ad hoc.
May 10, 2013
On Friday, 10 May 2013 at 15:12:01 UTC, Artur Skawina wrote:
> On 05/10/13 14:32, deadalnix wrote:
>> http://www.deadalnix.me/2013/05/10/type-safe-tagged-union-in-d-programming-language/
>> 
>> A trick that I used to use more and more, so I ended up creating a generic solution and wrote an article about it.
>
> Nothing 'shameless' about it.
>
> But Real Programmers don't use mixins...
>
>    struct TU(TYPES...) {
>       union { TYPES data; }
>       ubyte type;
>       static assert(TYPES.length<=typeof(type).max);
>
>       T opAssign(T)(T a) {
>          foreach(N, TYPE; TYPES)
>             static if (is(T==TYPE)) {
>                type = N;
>                return data[N] = a;
>             }
>          assert(0);
>       }
>       this(T)(T a) { this = a; }
>
>       DT as(DT)() @property {
>          foreach(N, TYPE; TYPES)
>             static if (is(DT==TYPE)) {
>                if (type==N)
>                   return data[N];
>                else
>                   assert(0, "Cannot access a '"~typeString(type)~"' as "~DT.stringof);
>             }
>          assert(0);
>       }
> 
>       auto ref apply(alias f)() {
>          foreach(N, TYPE; TYPES)
>             static if (is(typeof(f(data[N])))) // Comment this line out for strict CT checks.
>                if (N==type)
>                   return f(data[N]);
>          assert(0, "Could not apply '"~typeof(f).stringof~"' to "~typeString(type));
>       }
> 
>       static string typeString()(typeof(type) n) {
>          foreach(N, TYPE; TYPES)
>             if (N==n)
>                return TYPE.stringof;
>          assert(0);
>       }
>    }
>
>    double sqr(double a) { return a*a; }
>    int sqr(int a) { return a*a; }
>
>    void main() {
>       import std.stdio;
>       TU!(int, double, string) u;
>       u = 257;
>       writeln(u);
>       writeln(u.data[0], ", ", u.data[1]);
>       writeln(u.as!int);
>       //writeln(u.as!double); // RT error
>       writeln(u.apply!sqr());
>       u = 3.14;
>       writeln(u.apply!sqr());
>       u = "blah";
>       //writeln(u.apply!sqr()); // CT error in 'strict' mode, RT error otherwise.
> 
>       // Not currently accepted:
>       //writeln(u.apply!(function(a){return a*a;})());
>       //writeln(u.apply!(a=>a*a)());
>    }
>
> Something that wasn't obvious from your examples is that templates are not necessary
> when implementing the 'processing' functions - overloading is enough.
>
> The interesting aspect of this is what improvements to the language would help to
> make this code both a) simpler and more readable, and b) even more efficient.
> Manual optimizations, such as 'if-sequnences'->'switch', should /not/ result in
> harder to read code. The locals-can't-be-parms-to-local-templates restriction
> should only apply when really necessary (for example: static functions/lambdas can
> be allowed). Etc.
>
> artur

Nice improvement, especially the opAssign.

To be 100% fait, I didn't implemented it as I didn't needed it, but destruction is also something that can go wrong. I sure like the absence of mixins !
May 10, 2013
W dniu 10.05.2013 14:32, deadalnix pisze:
> http://www.deadalnix.me/2013/05/10/type-safe-tagged-union-in-d-programming-language/
>
>
> A trick that I used to use more and more, so I ended up creating a
> generic solution and wrote an article about it.

Here's my try on this: https://github.com/pszturmaj/json-streaming-parser/blob/master/json.d#L111 lines 111-184. It supports Self notation, so it's possible to create recursive unions given that Self is accessible through some indirection. TypeTag should be an enum with increasing values starting with 0. I just noticed, opAssign is prepended with underscore, I probably forgot to remove it after debugging:)
May 10, 2013
On 5/10/13 10:15 AM, deadalnix wrote:
> On Friday, 10 May 2013 at 13:51:11 UTC, deadalnix wrote:
>>> Is this on Reddit yet?
>>
>> No, feel free to put it if you think it is appropriate !
>
> http://www.reddit.com/r/programming/comments/1e2h99/type_safe_tagged_union_in_d/
>
>
> Someone else did.

I think this link went to spam. Posted here:

http://www.reddit.com/r/programming/comments/1e2x6a/typesafe_tagged_unions_in_the_d_programming/


Andrei
May 10, 2013
On 5/10/13 1:49 PM, Andrei Alexandrescu wrote:
> On 5/10/13 10:15 AM, deadalnix wrote:
>> On Friday, 10 May 2013 at 13:51:11 UTC, deadalnix wrote:
>>>> Is this on Reddit yet?
>>>
>>> No, feel free to put it if you think it is appropriate !
>>
>> http://www.reddit.com/r/programming/comments/1e2h99/type_safe_tagged_union_in_d/
>>
>>
>>
>> Someone else did.
>
> I think this link went to spam. Posted here:
>
> http://www.reddit.com/r/programming/comments/1e2x6a/typesafe_tagged_unions_in_the_d_programming/

A general note about posting to reddit: it often happens that posts from infrequent posters go to spam by means of some automatic rule. When that happens you need to message the moderators and politely ask them to manually instate the post because it's legit. Once you accumulate karma and all, your posts will be auto-approved.

I've done that for a while and accumulated good karma (and a good relationship with the mods to the extent that could be called such). So if you don't care about accumulating reddit points feel free to ask me to post links on your behalf. But of course the more strong posters in the D community, the better.


Andrei
May 10, 2013
On 5/10/2013 10:56 AM, Andrei Alexandrescu wrote:
> A general note about posting to reddit: it often happens that posts from
> infrequent posters go to spam by means of some automatic rule. When that happens
> you need to message the moderators and politely ask them to manually instate the
> post because it's legit. Once you accumulate karma and all, your posts will be
> auto-approved.
>
> I've done that for a while and accumulated good karma (and a good relationship
> with the mods to the extent that could be called such). So if you don't care
> about accumulating reddit points feel free to ask me to post links on your
> behalf. But of course the more strong posters in the D community, the better.

The post will also get a lot more upvotes if an abstract is also posted as the first comment on reddit. Otherwise, people won't click on the link.

May 10, 2013
On Friday, 10 May 2013 at 17:56:14 UTC, Andrei Alexandrescu wrote:
> A general note about posting to reddit: it often happens that posts from infrequent posters go to spam by means of some automatic rule. When that happens you need to message the moderators and politely ask them to manually instate the post because it's legit. Once you accumulate karma and all, your posts will be auto-approved.

Well that is stupid. It would be like StackOverflow closing questions of new users and waiting for people to vote to open.
May 10, 2013
On 05/10/2013 02:32 PM, deadalnix wrote:
> http://www.deadalnix.me/2013/05/10/type-safe-tagged-union-in-d-programming-language/
>
>
> A trick that I used to use more and more, so I ended up creating a
> generic solution and wrote an article about it.

I'd have implemented your TaggedUnion struct as follows. (I believe this is equivalent to your implementation.)

struct TaggedUnion(T...){
    private{
        union{ T members; }
        int tag;
        static int indexOf(S)(){
            foreach(i,t;T) static if(is(S==t)) return i;
            return -1;
        }
    }
    this(T)(T t) if(~indexOf!T){
        members[indexOf!T]=t;
        tag=indexOf!T;
    }
    auto ref apply(alias fun)(){
        switch(tag){
            foreach(i,_;T) case i: return fun(members[i]);
            default: assert(0);
        }
    }
}

But note that this is as unsafe as the original implementation. You will at least have to provide a postblit constructor and a destructor in order to keep the promise of safety.
May 12, 2013
On Friday, 10 May 2013 at 19:23:45 UTC, Jesse Phillips wrote:
> On Friday, 10 May 2013 at 17:56:14 UTC, Andrei Alexandrescu wrote:
>> A general note about posting to reddit: it often happens that posts from infrequent posters go to spam by means of some automatic rule. When that happens you need to message the moderators and politely ask them to manually instate the post because it's legit. Once you accumulate karma and all, your posts will be auto-approved.
>
> Well that is stupid. It would be like StackOverflow closing questions of new users and waiting for people to vote to open.

My submissions now all go to the spam section even though I have more than 1300 karma of comment and 800 karma of submission. It's fucking annoying.