digitalmars.D.learn - enum and tuples
- captaindet (21/21) Aug 08 2013 hi,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (69/72) Aug 09 2013 My feelings! :)
- captaindet (12/13) Aug 09 2013 thanks for the reply, Ali.
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (9/14) Aug 09 2013 I am very happy to hear that. It also makes me sad because I have been
- Dejan Lekic (5/23) Aug 10 2013 I could not agree more. TypeTuple is IMHO one of the coolest
- H. S. Teoh (53/68) Aug 09 2013 [...]
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (9/19) Aug 10 2013 Thank you and Jonathan. The above is exactly what helped me understand
- Jonathan M Davis (16/39) Aug 09 2013 I think that you have it at least mostly right, though I skimmed over mo...
- anonymous (4/7) Aug 09 2013 FWIW, it's an error in the current git head dmd: "Error: cannot
- Jonathan M Davis (10/25) Aug 09 2013 one
- captaindet (17/29) Aug 10 2013 hmm, but it is a TypeTuple of strings and aren't they supposed to
- Jonathan M Davis (10/46) Aug 10 2013 I don't know why you're seeing the problems that you're seeing
- captaindet (4/10) Aug 11 2013 thanks jonathan. yours and ali's explanations have been very helpful to ...
hi, i am still struggling getting to grips with tuples, especially typetuples. i got into this when trying module introspection and the surprise discovery that __traits(allMembers, .) seems to return a typetuple of strings. (the tuple article on dlang and philippe's template tutorial do help a bit, but only so much.) typetuples seem to live in a shadow world and quite obscurely should be referred to/passed around via aliases. even though we have alias a = b now i regard this as an irregularity/oddity of the language, i.e. that they are not treated the same way as variables/aggregates. anyhow, i started playing a bit putting them in enums anyway. surprisingly, "storing" tuples and typetuples in enums is accepted by the compiler. however, while enum tuples seem to behave normal/useful at compile time and run time, enum'ed typetuples don't like compile time, but seem to behave at runtime. (i rather would have expected the other way around). examples further below. so i guess my questions are a) if we are not allowed to put typetuples in enums, why is it not an error? b) if enums are supposed to handle typetuples, why is it not working at compile time? /det module demo; import std.stdio, std.typetuple, std.typecons; enum ok = tuple("one", "two", "three"); pragma(msg, ok, ", ", ok[0]); // Tuple("one", "two", "three"), one enum er = TypeTuple!("one", "two", "three"); // pragma(msg, er); // Error: variable _er_field_0,1,2 cannot be read at compile time void main(){ writeln("ok: ", ok, " ok[0]: ", ok[0]); // ok: Tuple!(string, string, string)("one", "two", "three") ok[0]: one writeln("er: ", er, " er[0]: ", er[0]); // er: onetwothree er[0]: one }
Aug 08 2013
On 08/08/2013 11:16 PM, captaindet wrote:> hi,i am still struggling getting to grips with tuples, especially typetuples.Yes, especially TypeTuples. :)typetuples seem to live in a shadow worldMy feelings! :) Coincidentally, I am struggling with the same question at the moment as I am in the process of revising and translating a Tuples chapter. I got stuck just yesterday but I have not re-read Philippe Sigaud's document yet. I don't answer your questions; the following is some of what I understand so far: import std.stdio; import std.typetuple; void foo(int i, string s, double d) { writefln("foo: %s %s %s", i, s, d); } void main() { // A TypeTuple is nothing but a combination of three separate entities, // loosely kept together. The following is one that is made of three // values: auto var = TypeTuple!(10, "hello", 1.5); // Although it looks like foo is receiving a single entity, because var is // a list of three entities (not actually a single entity of three // things), it matches what foo expects: foo(var); // prints: "foo: 10 hello 1.5" } Mixing values and types in a TypeTuple changes the kind of the TypeTuple and it becomes something different. Let's say I want it to represent the need of "give me a string array of 10 elements". This can be done by a value and a type: auto var = TypeTuple!(10, string); // compilation ERROR Yeah, although TypeTuple!(10, string) is legal syntax, it cannot be used in the same way as a TypeTuple that consists entirely of values. However, although the alias is only for convenience, the following works: alias var = TypeTuple!(10, string); In this case we know that var[1] is a type itself and var[0] is an int value. So, we can use them in that way: alias var = TypeTuple!(10, string); alias ElemType = var[1]; // it is the 'string' type itself auto length = var[0]; // it is 10 auto arr = new ElemType[length]; writeln(arr); // prints ["", "", "", "", "", "", "", "", "", ""] One difference between a TypeTuple that consists merely of values and a TypeTuple that consists at least one type is that the former can be used as a function parameter list as well as a template parameter lest. However, the latter can only be used as a template parameter list. (This is because a type cannot appear as a function argument.) For example, when combined with compile time foreach, the template can test each argument separately with a static if: void bar(T...)() { foreach (arg; T) { static if (is (arg)) { // I have a type auto var = arg.init; writefln("bar has just created a %s.init.", arg.stringof); } else { // I have a value writefln("bar is looking at the value %s.", arg); } } } alias var = TypeTuple!(10, string); bar!var(); /* Prints: bar is looking at the value 10. bar has just created a string.init. */ Ali
Aug 09 2013
On 2013-08-09 11:36, Ali Çehreli wrote:as I am in the process of revising and translating a Tuples chapter.thanks for the reply, Ali. as a matter of fact, i am checking your website regularly, eagerly awaiting the translations of the tuples chapter. and the __traits and the template chapter too ;) your examples make things a bit clearer in general, but not in the specific case of enums. i investigated my enum cases a bit more and it seems that enums of string value typetuples are good-natured expression by far and large, only pragma(msg, X) fails terribly. enum X = TypeTuple!("only", "strings", "here"); // fine everywhere but pragma(msg hovever, enums of integer or float value typetuples throw a phobos error when appearing outside of main(), but work alright within main() enum er = TypeTuple!(1,2,3); // ...\utf.d(1147): Error: cannot cast int to (int, int, int) void main(){ enum er = TypeTuple!(1,2,3); // fine } quite mysterious. /det
Aug 09 2013
On 08/09/2013 12:41 PM, captaindet wrote:On 2013-08-09 11:36, Ali Çehreli wrote:as I am in the process of revising and translating a Tuples chapter.as a matter of fact, i am checking your website regularly, eagerly awaiting the translations of the tuples chapter. and the __traits and the template chapter too ;)I am very happy to hear that. It also makes me sad because I have been very slow this summer. :-/ In fact, I was in the middle of translating the "More Templates" chapter that I realized I should move tuples before that one. I further realized that TypeTuple deserves more information than a couple of paragraphs and a trivial use in a unittest. ;) And that's when I realized that TypeTuple is a very strange beast indeed. Ali
Aug 09 2013
On Friday, 9 August 2013 at 21:24:30 UTC, Ali Çehreli wrote:On 08/09/2013 12:41 PM, captaindet wrote:I could not agree more. TypeTuple is IMHO one of the coolest features that is so underrated! Btw, Ali, everybody loves your book anyway. I recommend the section about Ranges to everyone. :D Keep up with the good work!On 2013-08-09 11:36, Ali Çehreli wrote:chapter.as I am in the process of revising and translating a Tuplesas a matter of fact, i am checking your website regularly,eagerlyawaiting the translations of the tuples chapter. and the__traits andthe template chapter too ;)I am very happy to hear that. It also makes me sad because I have been very slow this summer. :-/ In fact, I was in the middle of translating the "More Templates" chapter that I realized I should move tuples before that one. I further realized that TypeTuple deserves more information than a couple of paragraphs and a trivial use in a unittest. ;) And that's when I realized that TypeTuple is a very strange beast indeed. Ali
Aug 10 2013
On Fri, Aug 09, 2013 at 09:36:16AM -0700, Ali Çehreli wrote:On 08/08/2013 11:16 PM, captaindet wrote:> hi,[...] According to my understanding (please correct me if I'm wrong), there are two *different* kinds of tuples, which may be the source of much of the confusion surrounding tuples. 1) There's the built-in tuple, which is a compiler concept, and basically means any sequential collections of "things" (for lack of a better word). For example, you can have a sequence of types, like (int, string, float), or a sequence of values, like (1, "a", 3.0), or even a mixture of both, like (1, int, "a", float, string, 3.14). These sequences are called "tuples". They have no direct representation in the language's syntax, but they are an underlying concept that exists in the language specs and in the compiler. This concept allows us to deal with variadic functions/templates in a nice way: we abstract away the list of function/template arguments and say those arguments are tuples, so then if something else produces or returns a tuple, then we can plug that in where a parameter list would be expected. This allows us to construct templates the perform various manipulations on tuples, like reordering elements, filtering elements, etc.. These "internal tuples", if you wish to call them that, behave almost like arrays -- they have .length, and you can dereference them with array indexing notation like t[0], t[1], which is what happens when you write a variadic function: auto f(T...)(T args) { // args is a tuple containing function arguments auto a = args[0]; // a = 1, when called from main() below auto b = args[1]; // b = "a" auto c = args[2]; // c = 3.14 auto n = args.length; // n = 3, there are 3 arguments } void main() { f(1, "a", 3.14); } However, unlike arrays, tuples are not full-fledged runtime objects; you can't manipulate them at runtime like real arrays, and any loop over them is always unrolled at compile-time (because each tuple element may be a different type, so it's not possible to have the same loop body in machine code to process every element). 2) Phobos defines a tuple() function, that wraps an internal tuple of values inside a struct called Tuple. This allows a nicer interface to work with tuples of values, since you can explicitly create them, pass them around like runtime objects, etc.. They are more like structs with anonymous members, if you like, which are accessed with array indexing notation. They are NOT the same as internal tuples (though their implementation uses internal tuples), so you can't pass them to variadic functions and expect them to behave the same way (though I believe there *is* a method that returns the internal tuple out of a Tuple struct, so you can use that to get at the "raw" tuple when you need to). Phobos' TypeTuples (in std.typetuple), I believe, are basically just an alias that allows you to explicitly declare and use the internal tuples, so they are basically the same as (1). Hope this helps! :) T -- Guns don't kill people. Bullets do.i am still struggling getting to grips with tuples, especially typetuples.Yes, especially TypeTuples. :)typetuples seem to live in a shadow worldMy feelings! :) Coincidentally, I am struggling with the same question at the moment as I am in the process of revising and translating a Tuples chapter. I got stuck just yesterday but I have not re-read Philippe Sigaud's document yet.
Aug 09 2013
On 08/09/2013 10:41 AM, H. S. Teoh wrote:1) There's the built-in tuple, which is a compiler concept, and basically means any sequential collections of "things" (for lack of a better word). For example, you can have a sequence of types, like (int, string, float), or a sequence of values, like (1, "a", 3.0), or even a mixture of both, like (1, int, "a", float, string, 3.14). These sequences are called "tuples".Thank you and Jonathan. The above is exactly what helped me understand them finally. Your explanation matches my understanding exactly.we abstract away the list of function/template arguments and say those arguments are tuples, so then if something else produces or returns a tuple, then we can plug that in where a parameter list would be expected.That was the missing piece of the puzzle for me. And a very important point to make is that "the list of function/template arguments" are not TypeTuples. TypeTuple is just a tool that makes them available to the code. Thank you, Ali
Aug 10 2013
On Friday, August 09, 2013 10:41:05 H. S. Teoh wrote:On Fri, Aug 09, 2013 at 09:36:16AM -0700, Ali Çehreli wrote:[snip]On 08/08/2013 11:16 PM, captaindet wrote:> hi,[...] According to my understanding (please correct me if I'm wrong), there are two *different* kinds of tuples, which may be the source of much of the confusion surrounding tuples.i am still struggling getting to grips with tuples, especially typetuples.Yes, especially TypeTuples. :)typetuples seem to live in a shadow worldMy feelings! :) Coincidentally, I am struggling with the same question at the moment as I am in the process of revising and translating a Tuples chapter. I got stuck just yesterday but I have not re-read Philippe Sigaud's document yet.Hope this helps! :)I think that you have it at least mostly right, though I skimmed over most of it, so you might have a minor detail wrong somewhere. The compiler's tuples (TypeTuples) are basically what template and function parameter and argument lists are. TypeTuple itself is then just an alias for them so that you can actually declare and refer to them directly. It's kind of a travesty that they're referred to as tuples, and I really wish that they'd stop being referred to as that, but Walter keeps using the term tuple for them. Personally, I just always call them TypeTuples (as bad as that name is), though technically TypeTuple is just the alias. Regardless, they're completely a compile-time construct, unlike std.typecons.Tuple, which is a real tuple type. Really, the problem is the terminology used. It makes it all way more confusing than it should be. - Jonathan M Davis
Aug 09 2013
On Friday, 9 August 2013 at 06:16:20 UTC, captaindet wrote:a) if we are not allowed to put typetuples in enums, why is it not an error?[...]enum er = TypeTuple!("one", "two", "three");FWIW, it's an error in the current git head dmd: "Error: cannot cast "one" to (string, string, string) at compile time".
Aug 09 2013
On Friday, August 09, 2013 01:16:12 captaindet wrote:module demo; import std.stdio, std.typetuple, std.typecons; enum ok = tuple("one", "two", "three"); pragma(msg, ok, ", ", ok[0]); // Tuple("one", "two", "three"), one enum er = TypeTuple!("one", "two", "three"); // pragma(msg, er); // Error: variable _er_field_0,1,2 cannot be read at compile timeI'm pretty sure that this is just a bad error message.void main(){ writeln("ok: ", ok, " ok[0]: ", ok[0]); // ok: Tuple!(string, string, string)("one", "two", "three") ok[0]:onewriteln("er: ", er, " er[0]: ", er[0]); // er: onetwothree er[0]: one }What I expect is happening is that TypeTuples don't convert to string, so the pragma fails, but in the writeln, because writeln is variadic, it unrolls the TypeTuple, giving you writeln("er: ", er[0], er[1], er[2]], "er[0]: ", er[0]); and that works just fine, as each individual element in er converts to string just fine (particularly since they actually _are_ strings in this case). - Jonathan M Davis
Aug 09 2013
I'm pretty sure that this is just a bad error message.hmm, but it is a TypeTuple of strings and aren't they supposed to automatically expand? and pragma(msg, ...) takes various arguments, e.g. pragma(msg, "this", "and", "that"); so is it just a bad error message or a "bug" in pragma(msg, ...)? (..,i know, pragmas are difficult to blame for anything as they are not part of the language proper. but in lieu of a compile time print this is all we got for debugging our meta stuff.) then there is the thing of assigning value type TypeTuples to variables/enums. is this allowed or not? see my observations regarding enums which are for 2.063.2. according to anonymous in the git head for 2.064 the enum example for string value TypeTuples now fails...i don't think any of this behavior is documented anywhere. what i think is missing is a clearly defined boundary/set of rules for what we can do with the internal "tuples" (aka TypeTuples) and how, and what not. /detvoid main(){ writeln("ok: ", ok, " ok[0]: ", ok[0]); // ok: Tuple!(string, string, string)("one", "two", "three") ok[0]:onewriteln("er: ", er, " er[0]: ", er[0]); // er: onetwothree er[0]: one }What I expect is happening is that TypeTuples don't convert to string, so the pragma fails,
Aug 10 2013
On Sunday, August 11, 2013 07:24:52 captaindet wrote:I don't know why you're seeing the problems that you're seeing pragma(msg, "this", "and", "that"); seems to work, so I'd have expected the TypeTuple to work. I expect that it's a compiler bug. And yes, TypeTuples should definitely be assignable to enums (though where you can use such an enum depends on where you can use a TypeTuple - the enum's value is essentially copy-pasted wherever the enum is used). I think that things are far more confusing for you due to compiler bugs. - Jonathan M DavisI'm pretty sure that this is just a bad error message.hmm, but it is a TypeTuple of strings and aren't they supposed to automatically expand? and pragma(msg, ...) takes various arguments, e.g. pragma(msg, "this", "and", "that"); so is it just a bad error message or a "bug" in pragma(msg, ...)? (..,i know, pragmas are difficult to blame for anything as they are not part of the language proper. but in lieu of a compile time print this is all we got for debugging our meta stuff.) then there is the thing of assigning value type TypeTuples to variables/enums. is this allowed or not? see my observations regarding enums which are for 2.063.2. according to anonymous in the git head for 2.064 the enum example for string value TypeTuples now fails...i don't think any of this behavior is documented anywhere. what i think is missing is a clearly defined boundary/set of rules for what we can do with the internal "tuples" (aka TypeTuples) and how, and what not.void main(){ writeln("ok: ", ok, " ok[0]: ", ok[0]); // ok: Tuple!(string, string, string)("one", "two", "three")ok[0]:onewriteln("er: ", er, " er[0]: ", er[0]); // er: onetwothree er[0]: one }What I expect is happening is that TypeTuples don't convert to string, so the pragma fails,
Aug 10 2013
On 2013-08-11 01:59, Jonathan M Davis wrote:seems to work, so I'd have expected the TypeTuple to work. I expect that it's a compiler bug. And yes, TypeTuples should definitely be assignable to enums (though where you can use such an enum depends on where you can use a TypeTuple - the enum's value is essentially copy-pasted wherever the enum is used). I think that things are far more confusing for you due to compiler bugs.thanks jonathan. yours and ali's explanations have been very helpful to understand what is going on. i filed a bug report: http://d.puremagic.com/issues/show_bug.cgi?id=10803 /det
Aug 11 2013