Thread overview
Tuples?
Feb 09, 2006
Kramer
Feb 09, 2006
Sean Kelly
Feb 09, 2006
Oskar Linde
Feb 09, 2006
Kramer
Feb 09, 2006
Sean Kelly
Feb 09, 2006
Sean Kelly
Feb 13, 2006
Walter Bright
Feb 13, 2006
Sean Kelly
February 09, 2006
Is there any way to simulate tuples in D currently?  (hopefully that doesn't
look too hackish <g>)

Thanks in advance.

-Kramer


February 09, 2006
Kramer wrote:
> Is there any way to simulate tuples in D currently?  (hopefully that doesn't
> look too hackish <g>)

Yes.  I just threw this example together so it could do with a bit of cleaning up, but it works.  My only major complaint is that template functions can't be overloaded, thus the 'get' and 'set' methods.  Also, if you specify an out of range index, the current behavior will just do nothing or return an instance of Empty--a better approach might be to have a "static assert(false)" in there:

import std.c.stdio;

void main()
{
    MakeTuple!(int, long) t;

    printf( "%i\n", t.length );
    printf( "%i\n", t.get!(0) );
    printf( "%lli\n", t.get!(1) );
    t.set!(0) = 1;
    printf( "%i\n", t.get!(0) );
}

struct Empty
{

}

template Tuple( HeadType, TailType = Empty )
{
    struct Tuple
    {
        alias HeadType Type;

        TailType       tail;

        int length()
        {
            return Length!( Tuple );
        }

        template get( int n )
        {
            TypeAt!(n,Tuple) get()
            {
                static if( n == 0 )
                    return m_val;
                else static if( is( typeof( tail ) == Empty ) )
                    return tail;
                else
                    return tail.get!( n - 1 );
            }
        }

        template set( int n )
        {
            void set( TypeAt!(n,Tuple) newval )
            {
                static if( n == 0 )
                    m_val = newval;
                else static if( is( typeof( tail ) == Empty ) )
                    ; // do nothing
                else
                    return tail.set!( n - 1 )( newval );
            }
        }

    private:
        HeadType    m_val;
    }
}

template Length( T )
{
    static if( is( T == Empty ) )
        const int Length = 0;
    else
        const int Length = 1 + .Length!( typeof( T.tail ) );
}

template TypeAt( int pos, T )
{
    static if( is( T == Empty ) )
        alias Empty TypeAt;
    else static if( pos == 0 )
        alias T.Type TypeAt;
    else
        alias .TypeAt!( pos - 1, typeof( T.tail ) ) TypeAt;
}

template MakeTuple( T1 )
{
    alias Tuple!( T1 ) MakeTuple;
}

template MakeTuple( T1, T2 )
{
    alias Tuple!( T1, Tuple!( T2 ) ) MakeTuple;
}
February 09, 2006
In article <dsf3q0$1497$1@digitaldaemon.com>, Sean Kelly says...
>
>Kramer wrote:
>> Is there any way to simulate tuples in D currently?  (hopefully that doesn't
>> look too hackish <g>)
>
>Yes.  I just threw this example together so it could do with a bit of cleaning up, but it works.  My only major complaint is that template functions can't be overloaded, thus the 'get' and 'set' methods. Also, if you specify an out of range index, the current behavior will just do nothing or return an instance of Empty--a better approach might be to have a "static assert(false)" in there:
>
[snip]
>
>template MakeTuple( T1 )
>{
>     alias Tuple!( T1 ) MakeTuple;
>}
>
>template MakeTuple( T1, T2 )
>{
>     alias Tuple!( T1, Tuple!( T2 ) ) MakeTuple;
>}

I also threw together a quick Tuple. Actually two different implementations. Interestingly, one was almost identical to the above. Even most of the type and identifier names were the same. :) MakeTuple is just a bit more briefly implemented:

# template MakeTuple(T1=Empty, T2=Empty, T3=Empty, T4=Empty,
#                    T5=Empty, T6=Empty, T7=Empty, T8=Empty) {
#   static if (is(T1 == Empty))
#     alias Empty MakeTuple;
#   else
#     alias Tuple!(T1,MakeTuple!(T2,T3,T4,T5,T6,T7,T8)) MakeTuple;
# }

(This is just an attempt at a general implementation of ... for template
arguments)

The other version is not as elegant and more limited, but maybe a bit more straightforward:

#import std.stdio;
#
#typedef void nulltype;
#
#struct Tuple(T1=nulltype, T2=nulltype, T3=nulltype, T4=nulltype) {
#  static if (!is(T1 == nulltype))
#    T1 v1;
#  static if (!is(T2 == nulltype))
#    T2 v2;
#  static if (!is(T3 == nulltype))
#    T3 v3;
#  static if (!is(T4 == nulltype))
#    T4 v4;
#  static if (!is(T1 == nulltype)) {
#    void assignTo(out T1 o1) {
#      o1 = v1;
#    }
#    static if (!is(T2 == nulltype)) {
#      void assignTo(out T1 o1, out T2 o2) {
#        o1 = v1; o2 = v2;
#      }
#      static if (!is(T3 == nulltype)) {
#        void assignTo(out T1 o1, out T2 o2, out T3 o3) {
#          o1 = v1; o2 = v2; o3 = v3;
#        }
#        static if (!is(T4 == nulltype)) {
#          void assignTo(out T1 o1, out T2 o2, out T3 o3, out T4 o4) {
#            o1 = v1; o2 = v2; o4 = v4;
#          }
#        }
#      }
#    }
#  }
#}
#
#
#Tuple!(int,float) func() {
#  Tuple!(int,float) ret;
#  ret.v1 = 3;
#  ret.v2 = 3.5;
#  return ret;
#}
#
#int main() {
#  Tuple!(int,float) x = func();
#  writefln("%s %s",x.v1,x.v2);
#
#  int i;
#  float f;
#  func().assignTo(i,f);
#  writefln("%s %s",i,f);
#
#  return 0;
#}

/Oskar


February 09, 2006
Sean Kelly wrote:
> Kramer wrote:
>> Is there any way to simulate tuples in D currently?  (hopefully that doesn't
>> look too hackish <g>)
> 
> Yes.  I just threw this example together so it could do with a bit of cleaning up, but it works.  My only major complaint is that template functions can't be overloaded, thus the 'get' and 'set' methods.

It turns out that I was still thinking with a C++ mindset.  No methods need to be defined at all--this can all be done using consts and aliases--however, there appears to be a bug preventing this from working with structs.  I'm going to rewrite the tuple example with classes and it can be converted to a struct whenever this is fixed.  Stay tuned.


Sean
February 09, 2006
In article <dsf66t$19jb$1@digitaldaemon.com>, Oskar Linde says...
>
>In article <dsf3q0$1497$1@digitaldaemon.com>, Sean Kelly says...
>>
>>Kramer wrote:
>>> Is there any way to simulate tuples in D currently?  (hopefully that doesn't
>>> look too hackish <g>)
>>
>>Yes.  I just threw this example together so it could do with a bit of cleaning up, but it works.  My only major complaint is that template functions can't be overloaded, thus the 'get' and 'set' methods. Also, if you specify an out of range index, the current behavior will just do nothing or return an instance of Empty--a better approach might be to have a "static assert(false)" in there:
>>
>[snip]
>>
>>template MakeTuple( T1 )
>>{
>>     alias Tuple!( T1 ) MakeTuple;
>>}
>>
>>template MakeTuple( T1, T2 )
>>{
>>     alias Tuple!( T1, Tuple!( T2 ) ) MakeTuple;
>>}
>
>I also threw together a quick Tuple. Actually two different implementations. Interestingly, one was almost identical to the above. Even most of the type and identifier names were the same. :) MakeTuple is just a bit more briefly implemented:
>
># template MakeTuple(T1=Empty, T2=Empty, T3=Empty, T4=Empty,
>#                    T5=Empty, T6=Empty, T7=Empty, T8=Empty) {
>#   static if (is(T1 == Empty))
>#     alias Empty MakeTuple;
>#   else
>#     alias Tuple!(T1,MakeTuple!(T2,T3,T4,T5,T6,T7,T8)) MakeTuple;
># }
>
>(This is just an attempt at a general implementation of ... for template
>arguments)
>
>The other version is not as elegant and more limited, but maybe a bit more straightforward:
>
>#import std.stdio;
>#
>#typedef void nulltype;
>#
>#struct Tuple(T1=nulltype, T2=nulltype, T3=nulltype, T4=nulltype) {
>#  static if (!is(T1 == nulltype))
>#    T1 v1;
>#  static if (!is(T2 == nulltype))
>#    T2 v2;
>#  static if (!is(T3 == nulltype))
>#    T3 v3;
>#  static if (!is(T4 == nulltype))
>#    T4 v4;
>#  static if (!is(T1 == nulltype)) {
>#    void assignTo(out T1 o1) {
>#      o1 = v1;
>#    }
>#    static if (!is(T2 == nulltype)) {
>#      void assignTo(out T1 o1, out T2 o2) {
>#        o1 = v1; o2 = v2;
>#      }
>#      static if (!is(T3 == nulltype)) {
>#        void assignTo(out T1 o1, out T2 o2, out T3 o3) {
>#          o1 = v1; o2 = v2; o3 = v3;
>#        }
>#        static if (!is(T4 == nulltype)) {
>#          void assignTo(out T1 o1, out T2 o2, out T3 o3, out T4 o4) {
>#            o1 = v1; o2 = v2; o4 = v4;
>#          }
>#        }
>#      }
>#    }
>#  }
>#}
>#
>#
>#Tuple!(int,float) func() {
>#  Tuple!(int,float) ret;
>#  ret.v1 = 3;
>#  ret.v2 = 3.5;
>#  return ret;
>#}
>#
>#int main() {
>#  Tuple!(int,float) x = func();
>#  writefln("%s %s",x.v1,x.v2);
>#
>#  int i;
>#  float f;
>#  func().assignTo(i,f);
>#  writefln("%s %s",i,f);
>#
>#  return 0;
>#}
>
>/Oskar
>
>


Thanks for both replies.  I would love it if somehow this could be incorporated into the language or library.  But for the library, I'm guessing that would need implicit template instantiation?

-Kramer


February 09, 2006
Kramer wrote:
> 
> Thanks for both replies.  I would love it if somehow this could be incorporated
> into the language or library.  But for the library, I'm guessing that would need
> implicit template instantiation?

Not really.  'auto' is great for this sort of thing:

auto ret = someFunction(x,y,z);
int   a = ret.val!(0);
float b = ret.val!(1);

This is what I'm shooting for anyway.


Sean
February 13, 2006
"Sean Kelly" <sean@f4.ca> wrote in message news:dsgami$2cvr$2@digitaldaemon.com...
> No methods need to be defined at all--this can all be done using consts and aliases--however, there appears to be a bug preventing this from working with structs.

What's the bug?


February 13, 2006
Walter Bright wrote:
> "Sean Kelly" <sean@f4.ca> wrote in message news:dsgami$2cvr$2@digitaldaemon.com...
>> No methods need to be defined at all--this can all be done using consts and aliases--however, there appears to be a bug preventing this from working with structs.
> 
> What's the bug?

It turns out there are two issues.

This is the one regarding different behavior between structs and classes:

http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/6193

And in this one, the compiler doesn't seem to like aliasing scoped variables:

http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/6195

I narrowed down the above case here:

http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/6197

This last post also included a question--are aliases intended to be used in this way?  From what was in the spec, I wasn't entirely certain.

Sean