Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
February 09, 2006 Tuples? | ||||
---|---|---|---|---|
| ||||
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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kramer | 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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | 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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | 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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Oskar Linde | 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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kramer | 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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | "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 Re: Tuples? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | 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 |
Copyright © 1999-2021 by the D Language Foundation