www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Tuples?

reply Kramer <Kramer_member pathlink.com> writes:
Is there any way to simulate tuples in D currently?  (hopefully that doesn't
look too hackish <g>)

Thanks in advance.

-Kramer
Feb 08 2006
parent reply Sean Kelly <sean f4.ca> writes:
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; }
Feb 09 2006
next sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
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:

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
Feb 09 2006
parent reply Kramer <Kramer_member pathlink.com> writes:
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:

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
Feb 09 2006
parent Sean Kelly <sean f4.ca> writes:
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
Feb 09 2006
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
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
Feb 09 2006
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"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?
Feb 13 2006
parent Sean Kelly <sean f4.ca> writes:
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: digitalmars.D.bugs/6193 And in this one, the compiler doesn't seem to like aliasing scoped variables: digitalmars.D.bugs/6195 I narrowed down the above case here: 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
Feb 13 2006