Tuples

Diggory diggsey at googlemail.com
Sun May 26 19:24:51 PDT 2013


On Monday, 27 May 2013 at 01:36:58 UTC, Jonathan M Davis wrote:
> On Monday, May 27, 2013 11:21:08 Manu wrote:
>> I have certainly been confused by the term 'tuple' used in D 
>> countless
>> times.
>> It seems to exist in a variety of different contexts, and 
>> every time I
>> think I understood it, I realise I'm probably wrong some time 
>> later.
>> There seems to be poor/no documentation 
>> comparing/distinguishing various D
>> tuples, also, there seems to be no real explicit syntax, which 
>> makes it
>> hard to recognise.
>> I can kinda handle a Tuple template, and then there are these 
>> type tuples,
>> and then expression tuples? What is the relationship between 
>> these? Are
>> they compatible? How do I distinguish them?
>
> You basically just have to worry about Tuple and TypeTuple. 
> Tuple is of course
> very easy to understand. TypeTuple is then just an alias for 
> the built-in
> tuples, which can hold basically anything. They're what 
> template parameter
> lists, function parameter lists, template argument lists, and 
> function
> argument lists are made of. And you can use them handily in 
> other places (such
> as foreach) by using TypeTuple explicitly. I believe that an 
> expression tuple
> is simply a TypeTuple which holds only expressions. In 
> practice, I think that
> the differences are fairly simple, but they take quite a bit to 
> wrap your head
> around - primarily due to the terminology used rather than the 
> actual concept.
>
>> Someone that understand what they're talking about should take 
>> some time to
>> write a comprehensive article on the matter :)
>
> I guess that I'll have to look at doing that after I finish the 
> article that
> I'm writing on ranges (that I really need to finish...).
>
>> Some of the things I have read seem to presume that I already 
>> know what
>> it's talking about, and as a result, lead to dismissing or 
>> misunderstanding
>> the article.
>
> I generally know what's going on with D, but there were talks 
> at dconf that
> taught be stuff about D that I'd either forgotten or never 
> known (like some of
> what was going on with moves in Ali's talk). D is nowhere near 
> as bad C++ with
> regards to how complicated it is, but it's still quite 
> complicated.
>
>> I think the practical take-away from my experience is that it 
>> ends up as
>> one of those 'too hard' concepts, that I develop a tendency to 
>> actively
>> avoid dealing with because it's confused me a number of times.
>> I typically just start typing stuff and hope it works. And if 
>> it doesn't I
>> fiddle with it until it eventually does (or I give up), and I 
>> never
>> *really* understand why.
>> I'll bet I'm not the only one...
>
> It's well worth understanding TypeTuple well enough to use it 
> with foreach, as
> it's a great way to generate unit tests, particularly when 
> you're dealing with
> templated functions. Phobos does that quite a lot, particularly 
> with strings.
> Take splitLines unit test for example
>
>     foreach (S; TypeTuple!(char[], wchar[], dchar[], string, 
> wstring,
> dstring))
>     {
>         auto s =
> to!S("\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\n");
>
>         auto lines = splitLines(s);
>         assert(lines.length == 9);
>         assert(lines[0] == "");
>         assert(lines[1] == "peter");
>         assert(lines[2] == "");
>         assert(lines[3] == "paul");
>         assert(lines[4] == "jerry");
>         assert(lines[5] == "ice");
>         assert(lines[6] == "cream");
>         assert(lines[7] == "");
>         assert(lines[8] == "sunday");
>
>         lines = splitLines(s, KeepTerminator.yes);
>         assert(lines.length == 9);
>         assert(lines[0] == "\r");
>         assert(lines[1] == "peter\n");
>         assert(lines[2] == "\r");
>         assert(lines[3] == "paul\r\n");
>         assert(lines[4] == "jerry\u2028");
>         assert(lines[5] == "ice\u2029");
>         assert(lines[6] == "cream\n");
>         assert(lines[7] == "\n");
>         assert(lines[8] == "sunday\n");
>
>         s.popBack(); // Lop-off trailing \n
>         lines = splitLines(s);
>         assert(lines.length == 9);
>         assert(lines[8] == "sunday");
>
>         lines = splitLines(s, KeepTerminator.yes);
>         assert(lines.length == 9);
>         assert(lines[8] == "sunday");
>     }
>
> You get to unit test with 6 different types while only writing 
> the code once.
> That can be _extremely_ useful.
>
> - Jonathan M Davis

IMO we should have the following:

Tuple - Current Tuple implementation, equivalent to C++ tuple 
with the extra "naming" feature. Can be instantiated and passed 
around.

StaticTuple - Current TypeTuple implementation, equivalent to 
type of "..." parameter in template arguments. Should not be 
instantiable.

TypeTuple - A StaticTyple where all parts have been statically 
checked to be types. It should be easy to instantiate an actual 
Tuple using a TypeTuple. Note that the template system allows 
them to be the same type, ie. a StaticTuple!(int, float) == 
TypeTuple!(int, float) while a TypeTuple!("Hello") will fail to 
compile.

ExpressionTuple - A StaticTuple where all parts have been 
statically checked to be expressions.

It would be much easier to understand and it fills a big gap in 
the language - there's no guarantee than any methods such as 
"staticIndexOf" will work on the current "TypeTuple" if that 
tuple contains non-types. With the new system methods which can 
work on all types of static tuple can be moved to the 
"StaticTuple", while methods specific to a particular type of 
StaticTuple can be in the correct place.

It also shouldn't break any code since the only addition to 
TypeTuple is a check to make sure that the undocumented behaviour 
of using it with non-types is disallowed, and in the case that 
this undocumented feature is used the code can simply switch to 
StaticTuple and be done.

Another thing I'm not clear on is how "alias" template parameters 
interact with variadic parameters. Is it possible for a variadic 
parameter to be an alias? What happens if "alias T..." is used? 
(*goes off to check*)


More information about the Digitalmars-d mailing list