www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - Article on Tuples

reply Walter Bright <newshound digitalmars.com> writes:
http://www.digitalmars.com/d/tuple.html
Nov 15 2006
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
Seeing this: alias Tuple!(TP, 8) TR; // TR is now float,float,3,8 alias Tuple!(TP, TP) TS; // TS is float,float,3,float,float,3 makes me really wish the syntax for typedef/alias were: alias newname = oldname; I always thought the ordering for C++'s typedef was goofy. I get it backwards about half the time I think, just because it's basically an assignment perversely written the other way around from all other assignments. --bb
Nov 15 2006
parent reply "Chris Miller" <chris dprogramming.com> writes:
On Wed, 15 Nov 2006 07:53:11 -0500, Bill Baxter <wbaxter gmail.com> wrot=
e:

 Seeing this:

    alias Tuple!(TP, 8) TR;  // TR is now float,float,3,8
    alias Tuple!(TP, TP) TS; // TS is float,float,3,float,float,3

 makes me really wish the syntax for typedef/alias were:

    alias newname =3D oldname;

 I always thought the ordering for C++'s typedef was goofy.  I get it  =
 backwards about half the time I think, just because it's basically an =
=
 assignment perversely written the other way around from all other  =
 assignments.

 --bb
Think of a variable declaration and then put alias/typedef on front of i= t; = ever since I thought of it like this I never made the mistake again. int foo; // new foo typedef int foo; // new foo
Nov 15 2006
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Chris Miller wrote:
 On Wed, 15 Nov 2006 07:53:11 -0500, Bill Baxter <wbaxter gmail.com> wrote:
 
 Seeing this:

    alias Tuple!(TP, 8) TR;  // TR is now float,float,3,8
    alias Tuple!(TP, TP) TS; // TS is float,float,3,float,float,3

 makes me really wish the syntax for typedef/alias were:

    alias newname = oldname;

 I always thought the ordering for C++'s typedef was goofy.  I get it 
 backwards about half the time I think, just because it's basically an 
 assignment perversely written the other way around from all other 
 assignments.

 --bb
Think of a variable declaration and then put alias/typedef on front of it; ever since I thought of it like this I never made the mistake again. int foo; // new foo typedef int foo; // new foo
You probably got the point, but what I meant was that types in D are really starting to look just like compile-time variables in a compile-time metaprogramming language. Since they have such a strong connection with runtime variables used in D's runtime language, it would be nice if the syntax for assigning to those compile-time type variables reflected that similarity, instead of clinging to the syntax chosen in the 70's by Mr. Ritchie before any of this was even dreamed of. As far as my messing up the order, I think the big problem is just that it's opposite to the order of my thinking. My thought process is usually something like 1) I need to use the type of a slot here. 2) Ugh, what was that type exactly? U delgate(T) or S delegate(U,V)? 3) It would be handy to have a slot_t alias to represent that. 4) ok, I'll make one: [/me types 'alias slot_t;'] 5) *then* I go searching around to figure out what the actual type is to fill in there. So I usually end up /writing/ it in the order 'alias', newname, oldname regardless of the order it appears on the screen. --bb
Nov 15 2006
prev sibling next sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
This does it! For the last 2 years I've been a bit uneasy about letting a metalanguage "grow" on top of D, and in the back of my head I've slowly gathered and assembled together parts needed for an ambitious metalanguage for D. But now I give up. Gotta admit, Walter, this is becoming simply Killer Stuff! Wish I could buy you a beer for this! Right now I feel an urge to run out on the street yelling You Aint Seen Nothin Yet!!! I feel like a tribesman who has been carrying this heavy crate through an enormous forest with the others, gathering mushrooms and berries and game to eventually bring home. And then there's this stone wall, and after some searching we find a gate, and when we open it we are blinded by the light of the endless fields ahead, virgin and rife with fruit trees and bushes with berries. To be the ones to have found these fields, we feel privileged, honored, and somehow even indebted! Indebted to have respect for this bounty, while still finding everything there with diligence and vigor, and putting it all to the very best uses we can think of, so that we know we can stay proud of what we've done. Standing there, before all this, we literally feel that History is in the Making, right here and right now. And we're in it! For the first time for many of us, we know at once that this is the very time, of which we'll be telling war stories to our children and grand children, for the rest of our lives. While normally such is realized only decades later, realizing it now makes us stand taller, prouder, and with extra resolve for the hardships that inevitably will face us before we're eventually home with the crate.
Nov 15 2006
parent reply BLS <Killing_Zoe web.de> writes:
Georg Wrede schrieb:
 Walter Bright wrote:
 
 http://www.digitalmars.com/d/tuple.html
Right now I feel an urge to run out on the street yelling You Aint Seen Nothin Yet!!!
Walter Turner Overdrive ! It is still a bit in the "fog" but the tuple/variadic parameter stuff should have some influence in implementing D collections. What do you think ? Björn
Nov 15 2006
parent reply Georg Wrede <georg.wrede nospam.org> writes:
BLS wrote:
 Georg Wrede schrieb:
 
 Walter Bright wrote:

 http://www.digitalmars.com/d/tuple.html
Right now I feel an urge to run out on the street yelling You Aint Seen Nothin Yet!!!
Walter Turner Overdrive ! It is still a bit in the "fog" but the tuple/variadic parameter stuff should have some influence in implementing D collections. What do you think ?
In the long run, I think there are few non-trivial template application areas where it wouldn't play a role.
Nov 15 2006
parent BLS <Killing_Zoe web.de> writes:
Georg Wrede schrieb:

 In the long run, I think there are few non-trivial template application 
 areas where it wouldn't play a role.
Would be nice to see something concrete. Björn
Nov 15 2006
prev sibling next sibling parent reply Don Clugston <dac nospam.com.au> writes:
Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
"A tuple is a sequence of elements. Those elements can be types, expressions, or aliases." Is this wording correct? How can you make an alias tuple? Or does this just mean an alias of another tuple? --- Normal C code reduces in size by ~20% when converted to D. But what happens to LOC when complex C++ template code is converted to D??? That's frightening. <g>
Nov 15 2006
next sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
Don Clugston wrote:

 Normal C code reduces in size by ~20%  when converted to D. But what 
 happens to LOC when complex C++ template code is converted to D??? 
 That's frightening. <g>
We'll have all of boost on the back of a napkin before you know it! --bb
Nov 15 2006
next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Bill Baxter wrote:
 Don Clugston wrote:
 
 Normal C code reduces in size by ~20%  when converted to D. But what 
 happens to LOC when complex C++ template code is converted to D??? 
 That's frightening. <g>
We'll have all of boost on the back of a napkin before you know it!
What is truly amazing is that our progress now feels almost exponential! That's unheard of, logarithmic is more like what you could expect, at best.
Nov 15 2006
prev sibling parent "John Reimer" <terminal.node gmail.com> writes:
On Wed, 15 Nov 2006 10:11:04 -0800, Bill Baxter <wbaxter gmail.com> wrote:

 Don Clugston wrote:

 Normal C code reduces in size by ~20%  when converted to D. But what  
 happens to LOC when complex C++ template code is converted to D???  
 That's frightening. <g>
We'll have all of boost on the back of a napkin before you know it! --bb
Its scary! D Templates have certainly come a long way! Congrats, Walter. A fine job. -JJR
Nov 15 2006
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
Don Clugston wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
"A tuple is a sequence of elements. Those elements can be types, expressions, or aliases." Is this wording correct? How can you make an alias tuple?
Just pass in symbols as template arguments to a U...
Nov 15 2006
parent reply Don Clugston <dac nospam.com.au> writes:
Walter Bright wrote:
 Don Clugston wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
"A tuple is a sequence of elements. Those elements can be types, expressions, or aliases." Is this wording correct? How can you make an alias tuple?
Just pass in symbols as template arguments to a U...
Awesome! This is even better than I thought. One problem -- it seems that if the tuple has a mix of types and instances, you can't index it. ------------- struct S { int x; long y; } template Tuple(E...) { alias E Tuple; } void main() { int q; alias Tuple!(S, q) Z; alias Z[0] R; // fails -- "tuple E is used as a type" } ------------- Also, is there any way to get .tupleof to return an alias tuple? For example, you can't write alias S.tupleof[0] R; Nor (more importantly) can you pass it as an template alias parameter: template Z(alias W) { const int Z = 2; } const int x = Z!((S.tupleof[0])); (If it worked, I could write a dump!(X) which would display all the names of the members of X, with their values...).
Nov 16 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Don Clugston wrote:
 One problem -- it seems that if the tuple has a mix of types and 
 instances, you can't index it.
 -------------
 struct S { int x; long y; }
 
 template Tuple(E...)
 {
     alias E Tuple;
 }
 
 void main()
 {
     int q;
 
     alias Tuple!(S, q) Z;
     alias Z[0] R; // fails -- "tuple E is used as a type"
 }
 -------------
About the only thing you can do with mixed tuples is pass them as arguments to another template.
 Also, is there any way to get .tupleof to return an alias tuple?
 For example, you can't write
 alias S.tupleof[0] R;
That's because you can't have an alias to an expression. You can have a pointer to an expression, though: auto R = &S.tupleof[0];
 Nor (more importantly) can you pass it as an template alias parameter:
 
 template Z(alias W) {
     const int Z = 2;
 }
 
 const int x = Z!((S.tupleof[0]));
 
 (If it worked, I could write a dump!(X) which would display all the 
 names of the members of X, with their values...).
Nov 16 2006
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Walter Bright wrote:
 Don Clugston wrote:
 One problem -- it seems that if the tuple has a mix of types and 
 instances, you can't index it.
 -------------
 struct S { int x; long y; }

 template Tuple(E...)
 {
     alias E Tuple;
 }

 void main()
 {
     int q;

     alias Tuple!(S, q) Z;
     alias Z[0] R; // fails -- "tuple E is used as a type"
 }
 -------------
About the only thing you can do with mixed tuples is pass them as arguments to another template.
 Also, is there any way to get .tupleof to return an alias tuple?
 For example, you can't write
 alias S.tupleof[0] R;
That's because you can't have an alias to an expression. You can have a pointer to an expression, though: auto R = &S.tupleof[0];
Indexed Tuples are only expressions in syntax, not such much conceptually. What if we could also index tuple elements using template instantiation: alias S.tupleof!(0) R; Then perhaps the aliasing would work with the current compiler/language rules. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Nov 18 2006
prev sibling next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
The one thing I didn't get was why there was two versions of the "Curry" template, one with a "Dummy" parameter. Can you explain? And then can you post the explanation on that page? Russ
Nov 15 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Russ Lewis wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
The one thing I didn't get was why there was two versions of the "Curry" template, one with a "Dummy" parameter. Can you explain? And then can you post the explanation on that page?
It's because you cannot overload two templates with the same parameter list. So we make them different by giving one a dummy parameter.
Nov 15 2006
parent reply Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Russ Lewis wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
The one thing I didn't get was why there was two versions of the "Curry" template, one with a "Dummy" parameter. Can you explain? And then can you post the explanation on that page?
It's because you cannot overload two templates with the same parameter list. So we make them different by giving one a dummy parameter.
Just to be clear, this limitation will eventually go away, correct? Sean
Nov 15 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Sean Kelly wrote:
 Walter Bright wrote:
 Russ Lewis wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
The one thing I didn't get was why there was two versions of the "Curry" template, one with a "Dummy" parameter. Can you explain? And then can you post the explanation on that page?
It's because you cannot overload two templates with the same parameter list. So we make them different by giving one a dummy parameter.
Just to be clear, this limitation will eventually go away, correct?
Maybe.
Nov 15 2006
parent reply Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Sean Kelly wrote:
 Walter Bright wrote:
 Russ Lewis wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
The one thing I didn't get was why there was two versions of the "Curry" template, one with a "Dummy" parameter. Can you explain? And then can you post the explanation on that page?
It's because you cannot overload two templates with the same parameter list. So we make them different by giving one a dummy parameter.
Just to be clear, this limitation will eventually go away, correct?
Maybe.
Ack! Related question :-) I assume this will work at some point?: T fn( T, U )( U val ) { return T.init; } void main() { int i = fn!(int)( 1.0 ); } Currently, I get: test.d(9): template instance fn!(int) does not match any template declaration test.d(9): Error: template instance 'fn!(int)' is not a variable test.d(9): Error: function expected before (), not fn!(int) of type int Sean
Nov 15 2006
parent reply Walter Bright <newshound digitalmars.com> writes:
Sean Kelly wrote:
 Ack! Related question :-)  I assume this will work at some point?:
 
   T fn( T, U )( U val )
   {
       return T.init;
   }
 
   void main()
   {
       int i = fn!(int)( 1.0 );
   }
 
 Currently, I get:
 
   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of type int
That's a hard one to get to work, as it has chicken-and-egg problems.
Nov 16 2006
parent reply Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 Sean Kelly wrote:
 Ack! Related question :-)  I assume this will work at some point?:

   T fn( T, U )( U val )
   {
       return T.init;
   }

   void main()
   {
       int i = fn!(int)( 1.0 );
   }

 Currently, I get:

   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of type int
That's a hard one to get to work, as it has chicken-and-egg problems.
Hrm... I think that one may eventually turn out to be fairly important. It's quite common to specify only the return type for template functions in C++. The most obvious example being the cast functions. Sean
Nov 16 2006
next sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Sean Kelly wrote:
 Walter Bright wrote:
 Sean Kelly wrote:
 Ack! Related question :-)  I assume this will work at some point?:

   T fn( T, U )( U val )
   {
       return T.init;
   }

   void main()
   {
       int i = fn!(int)( 1.0 );
   }

 Currently, I get:

   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of type 
 int
That's a hard one to get to work, as it has chicken-and-egg problems.
Hrm... I think that one may eventually turn out to be fairly important. It's quite common to specify only the return type for template functions in C++. The most obvious example being the cast functions.
You can use nested templates as a workaround: template myCast(T) { T myCast(U)(U val) { return cast(T) val; } } void main() { int i = myCast!(int)(1.0); }
Nov 16 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
Oskar Linde wrote:
 Sean Kelly wrote:
 Walter Bright wrote:
 Sean Kelly wrote:
 Ack! Related question :-)  I assume this will work at some point?:

   T fn( T, U )( U val )
   {
       return T.init;
   }

   void main()
   {
       int i = fn!(int)( 1.0 );
   }

 Currently, I get:

   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of 
 type int
That's a hard one to get to work, as it has chicken-and-egg problems.
Hrm... I think that one may eventually turn out to be fairly important. It's quite common to specify only the return type for template functions in C++. The most obvious example being the cast functions.
You can use nested templates as a workaround: template myCast(T) { T myCast(U)(U val) { return cast(T) val; } } void main() { int i = myCast!(int)(1.0); }
Nice trick! Sean
Nov 16 2006
prev sibling parent reply Bill Baxter <wbaxter gmail.com> writes:
Oskar Linde wrote:
 Sean Kelly wrote:
 
 Walter Bright wrote:

 Sean Kelly wrote:

 Ack! Related question :-)  I assume this will work at some point?:

   T fn( T, U )( U val )
   {
       return T.init;
   }

   void main()
   {
       int i = fn!(int)( 1.0 );
   }

 Currently, I get:

   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of 
 type int
That's a hard one to get to work, as it has chicken-and-egg problems.
Hrm... I think that one may eventually turn out to be fairly important. It's quite common to specify only the return type for template functions in C++. The most obvious example being the cast functions.
You can use nested templates as a workaround: template myCast(T) { T myCast(U)(U val) { return cast(T) val; } } void main() { int i = myCast!(int)(1.0); }
Bummer, that doesn't seem to work inside a class member template: class Foo { template myCast(T) { T myCast(U)(U val) { return cast(T) val; } } } void main() { Foo foo = new Foo; int i = foo.myCast!(int)(1.0); } --> Error: function expected before (), not 'foo dotexp template myCast(U)' --bb
Nov 17 2006
parent reply Sean Kelly <sean f4.ca> writes:
Bill Baxter wrote:
 Oskar Linde wrote:
 Sean Kelly wrote:

 Walter Bright wrote:

 Sean Kelly wrote:

 Ack! Related question :-)  I assume this will work at some point?:

   T fn( T, U )( U val )
   {
       return T.init;
   }

   void main()
   {
       int i = fn!(int)( 1.0 );
   }

 Currently, I get:

   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of 
 type int
That's a hard one to get to work, as it has chicken-and-egg problems.
Hrm... I think that one may eventually turn out to be fairly important. It's quite common to specify only the return type for template functions in C++. The most obvious example being the cast functions.
You can use nested templates as a workaround: template myCast(T) { T myCast(U)(U val) { return cast(T) val; } } void main() { int i = myCast!(int)(1.0); }
Bummer, that doesn't seem to work inside a class member template: class Foo { template myCast(T) { T myCast(U)(U val) { return cast(T) val; } } } void main() { Foo foo = new Foo; int i = foo.myCast!(int)(1.0); } --> Error: function expected before (), not 'foo dotexp template myCast(U)'
Hopefully, this is just a bug. If it can be made to work I don't see a pressing need for partial template argument evaluation. Sean
Nov 17 2006
parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Sean Kelly wrote:
 Bill Baxter wrote:
 Bummer, that doesn't seem to work inside a class member template:

 class Foo {
     template myCast(T) {
         T myCast(U)(U val) {
             return cast(T) val;
         }
     }
 }

 void main() {
   Foo foo = new Foo;
   int i = foo.myCast!(int)(1.0);
 }

 -->
 Error: function expected before (), not 'foo dotexp template myCast(U)'
Hopefully, this is just a bug. If it can be made to work I don't see a pressing need for partial template argument evaluation.
Attached is a small and ugly patch that should resolve this. I don't have a proper regression testing framework running, so it is quite the opposite of extensively tested and should be written much more properly. It just serves to illustrate that this is definitely fixable. /Oskar
Dec 01 2006
prev sibling parent xs0 <xs0 xs0.com> writes:
Sean Kelly wrote:
 Walter Bright wrote:
 Sean Kelly wrote:
 Ack! Related question :-)  I assume this will work at some point?:

   T fn( T, U )( U val )
   {
       return T.init;
   }

   void main()
   {
       int i = fn!(int)( 1.0 );
   }

 Currently, I get:

   test.d(9): template instance fn!(int) does not match any template 
 declaration
   test.d(9): Error: template instance 'fn!(int)' is not a variable
   test.d(9): Error: function expected before (), not fn!(int) of type 
 int
That's a hard one to get to work, as it has chicken-and-egg problems.
Hrm... I think that one may eventually turn out to be fairly important. It's quite common to specify only the return type for template functions in C++. The most obvious example being the cast functions. Sean
This works, though: import std.stdio; template foo(T) { T foo(U)(U u) { writefln(u); return T.init; } } void main() { int i = foo!(int)(1.5); } xs0
Nov 16 2006
prev sibling parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
You have the misspell "evaluatible" there. Also, for what I see in this article, the http://www.digitalmars.com/d/template.html spec doc is a bit incomplete. No mention that Tuples can be used to "declare variables", only parameters. I also found the statement "A Tuple is not a type," a bit misleading since it seems Tuples are heading in a direction that makes them *somewhat* a type (you can declare variables with them, and even return them from functions). Another potentially misleading statement is the: "Tuples are static compile time entities, there is no way to dynamically change, add, or remove elements." It's true for most tuples, but not quite so for a tuple-variable, since you can change the elements of a tuple-variable. Speaking of tuple variables, man, that is deep stuff :P . It took me a while to grok that and to come up with a conceptualization that made sense and fit adequately. I'm thinking that tuple-variables are somewhat like anonymous structs, they are tuples of values, which happen to be Lvalues too, unlike the other expression/value templates. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Nov 18 2006
parent Kyle Furlong <kylefurlong gmail.com> writes:
Bruno Medeiros wrote:
 Walter Bright wrote:
 http://www.digitalmars.com/d/tuple.html
You have the misspell "evaluatible" there. Also, for what I see in this article, the http://www.digitalmars.com/d/template.html spec doc is a bit incomplete. No mention that Tuples can be used to "declare variables", only parameters. I also found the statement "A Tuple is not a type," a bit misleading since it seems Tuples are heading in a direction that makes them *somewhat* a type (you can declare variables with them, and even return them from functions). Another potentially misleading statement is the: "Tuples are static compile time entities, there is no way to dynamically change, add, or remove elements." It's true for most tuples, but not quite so for a tuple-variable, since you can change the elements of a tuple-variable. Speaking of tuple variables, man, that is deep stuff :P . It took me a while to grok that and to come up with a conceptualization that made sense and fit adequately. I'm thinking that tuple-variables are somewhat like anonymous structs, they are tuples of values, which happen to be Lvalues too, unlike the other expression/value templates.
Basically, they rock. ;)
Nov 18 2006