www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Tuples

reply Russel Winder <russel winder.org.uk> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

I wonder if people coming to D, looking for information about tuples,
will get confused by http://dlang.org/tuple.html which seems to tell
people they have to "roll their own", and
http://dlang.org/phobos/std_typecons.html which tells people they have
been pre-rolled in the standard library?

--=20
Russel.
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D
Dr Russel Winder      t: +44 20 7585 2200   voip: sip:russel.winder ekiga.n=
et
41 Buckmaster Road    m: +44 7770 465 077   xmpp: russel winder.org.uk
London SW11 1EN, UK   w: www.russel.org.uk  skype: russel_winder
May 26 2013
next sibling parent "Diggory" <diggsey googlemail.com> writes:
On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote:
 I wonder if people coming to D, looking for information about 
 tuples,
 will get confused by http://dlang.org/tuple.html which seems to 
 tell
 people they have to "roll their own", and
 http://dlang.org/phobos/std_typecons.html which tells people 
 they have
 been pre-rolled in the standard library?

I found this especially confusing because the built-in Tuple is defined differently. The Tuple in that example is equivalent to the definition of TypeTuple, and yet TypeTuple is supposedly specific to types while that example (as so by implication TypeTuple) apparently works just as well with other contents. On top of that Tuple is the one that only works with types - any string expressions are extracted and used as names... Surely a tuple which can only store types should be a TypeTyple and a tuple which can store anything should be a Tuple.
May 26 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, May 26, 2013 22:38:24 Diggory wrote:
 On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote:
 I wonder if people coming to D, looking for information about
 tuples,
 will get confused by http://dlang.org/tuple.html which seems to
 tell
 people they have to "roll their own", and
 http://dlang.org/phobos/std_typecons.html which tells people
 they have
 been pre-rolled in the standard library?

I found this especially confusing because the built-in Tuple is defined differently. The Tuple in that example is equivalent to the definition of TypeTuple, and yet TypeTuple is supposedly specific to types while that example (as so by implication TypeTuple) apparently works just as well with other contents. On top of that Tuple is the one that only works with types - any string expressions are extracted and used as names... Surely a tuple which can only store types should be a TypeTyple and a tuple which can store anything should be a Tuple.

I really wish that the term tuple didn't get used with the built-in tuples / TypeTuples. They _aren't_ tuples. They're similar, but they don't nest, and they cause a lot of confusion with std.typecons.Tuple. And they're only compile-time constructs to boot. - Jonathan M Davis
May 26 2013
prev sibling next sibling parent Manu <turkeyman gmail.com> writes:
--089e01184b0e9c0b8804dda8f6d6
Content-Type: text/plain; charset=UTF-8

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?

Someone that understand what they're talking about should take some time to
write a comprehensive article on the matter :)
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 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...


On 27 May 2013 10:25, Jonathan M Davis <jmdavisProg gmx.com> wrote:

 On Sunday, May 26, 2013 22:38:24 Diggory wrote:
 On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote:
 I wonder if people coming to D, looking for information about
 tuples,
 will get confused by http://dlang.org/tuple.html which seems to
 tell
 people they have to "roll their own", and
 http://dlang.org/phobos/std_typecons.html which tells people
 they have
 been pre-rolled in the standard library?

I found this especially confusing because the built-in Tuple is defined differently. The Tuple in that example is equivalent to the definition of TypeTuple, and yet TypeTuple is supposedly specific to types while that example (as so by implication TypeTuple) apparently works just as well with other contents. On top of that Tuple is the one that only works with types - any string expressions are extracted and used as names... Surely a tuple which can only store types should be a TypeTyple and a tuple which can store anything should be a Tuple.

I really wish that the term tuple didn't get used with the built-in tuples / TypeTuples. They _aren't_ tuples. They're similar, but they don't nest, and they cause a lot of confusion with std.typecons.Tuple. And they're only compile-time constructs to boot. - Jonathan M Davis

--089e01184b0e9c0b8804dda8f6d6 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I have certainly been confused by the term &#39;tuple&#39;= used in D countless times.<div style>It seems to exist in a variety of dif= ferent contexts, and every time I think I understood it, I realise I&#39;m = probably wrong some time later.</div> <div style>There seems to be poor/no documentation comparing/distinguishing= various D tuples, also, there seems to be no real explicit syntax, which m= akes it hard to recognise.</div><div style>I can kinda handle a Tuple templ= ate, and then there are these type tuples, and then expression tuples? What= is the relationship between these? Are they compatible? How do I distingui= sh them?</div> <div style><br></div><div style>Someone that understand what they&#39;re ta= lking about should take some time to write a comprehensive article on the m= atter :)</div><div style>Some of the things I have read seem to presume tha= t I already know what it&#39;s talking about, and as a result, lead to dism= issing or misunderstanding the article.</div> <div style><br></div><div style>I think the practical take-away from my exp= erience is that it ends up as one of those &#39;too hard&#39; concepts, tha= t I develop a tendency to actively avoid dealing with because it&#39;s conf= used me a number of times.</div> <div style>I typically just start typing stuff and hope it works. And if it= doesn&#39;t I fiddle with it until it eventually does (or I give up), and = I never *really* understand why.</div><div style>I&#39;ll bet I&#39;m not t= he only one...</div> </div><div class=3D"gmail_extra"><br><br><div class=3D"gmail_quote">On 27 M= ay 2013 10:25, Jonathan M Davis <span dir=3D"ltr">&lt;<a href=3D"mailto:jmd= avisProg gmx.com" target=3D"_blank">jmdavisProg gmx.com</a>&gt;</span> wrot= e:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex"><div class=3D"HOEnZb"><div class=3D"h5">On S= unday, May 26, 2013 22:38:24 Diggory wrote:<br> &gt; On Sunday, 26 May 2013 at 15:48:00 UTC, Russel Winder wrote:<br> &gt; &gt; I wonder if people coming to D, looking for information about<br> &gt; &gt; tuples,<br> &gt; &gt; will get confused by <a href=3D"http://dlang.org/tuple.html" targ= et=3D"_blank">http://dlang.org/tuple.html</a> which seems to<br> &gt; &gt; tell<br> &gt; &gt; people they have to &quot;roll their own&quot;, and<br> &gt; &gt; <a href=3D"http://dlang.org/phobos/std_typecons.html" target=3D"_= blank">http://dlang.org/phobos/std_typecons.html</a> which tells people<br> &gt; &gt; they have<br> &gt; &gt; been pre-rolled in the standard library?<br> &gt;<br> &gt; I found this especially confusing because the built-in Tuple is<br> &gt; defined differently.<br> &gt;<br> &gt; The Tuple in that example is equivalent to the definition of<br> &gt; TypeTuple, and yet TypeTuple is supposedly specific to types<br> &gt; while that example (as so by implication TypeTuple) apparently<br> &gt; works just as well with other contents.<br> &gt;<br> &gt; On top of that Tuple is the one that only works with types - any<br> &gt; string expressions are extracted and used as names... Surely a<br> &gt; tuple which can only store types should be a TypeTyple and a<br> &gt; tuple which can store anything should be a Tuple.<br> <br> </div></div>I really wish that the term tuple didn&#39;t get used with the = built-in tuples /<br> TypeTuples. They _aren&#39;t_ tuples. They&#39;re similar, but they don&#39= ;t nest, and<br> they cause a lot of confusion with std.typecons.Tuple. And they&#39;re only= <br> compile-time constructs to boot.<br> <span class=3D"HOEnZb"><font color=3D"#888888"><br> - Jonathan M Davis<br> </font></span></blockquote></div><br></div> --089e01184b0e9c0b8804dda8f6d6--
May 26 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
May 26 2013
prev sibling next sibling parent "Diggory" <diggsey googlemail.com> writes:
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*)
May 26 2013
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, May 27, 2013 04:24:51 Diggory wrote:
 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.

Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere. Because you're generally in control of the TypeTuples that you're using (you aren't usually getting the from APIs and the like), I really don' think that the fact that it can hold both types and expressions is a big deal. I expect that it pretty much never causes problems in actual code. It just makes it so that the name sucks. I don't think that we'd gain much (if anything) by separating out TypeTuple into three different types. Renaming it would be nice, but given the current push to stop making breaking changes like that, I would expect that at best, we'd get an alias with a better name. - Jonathan M Davis
May 26 2013
prev sibling next sibling parent "Diggory" <diggsey googlemail.com> writes:
On Monday, 27 May 2013 at 02:31:50 UTC, Jonathan M Davis wrote:
 On Monday, May 27, 2013 04:24:51 Diggory wrote:
 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.

Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere. Because you're generally in control of the TypeTuples that you're using (you aren't usually getting the from APIs and the like), I really don' think that the fact that it can hold both types and expressions is a big deal. I expect that it pretty much never causes problems in actual code. It just makes it so that the name sucks. I don't think that we'd gain much (if anything) by separating out TypeTuple into three different types. Renaming it would be nice, but given the current push to stop making breaking changes like that, I would expect that at best, we'd get an alias with a better name. - Jonathan M Davis

Hmm, given that the fix can be entirely automated incredibly simply with find and replace it doesn't seem that bad, especially as the broken behaviour is undocumented. Given that the documentation specifically disambiguates between TypeTuples and ExpressionTuples I think at least emitting a warning when non-types are used to a TypeTuple is reasonable.
May 26 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 27 May 2013 at 02:31:50 UTC, Jonathan M Davis wrote:
 On Monday, May 27, 2013 04:24:51 Diggory wrote:
 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.

Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere.

Granted that nobody understand them, it is fair to say it should be changed.
May 26 2013
prev sibling next sibling parent "Diggory" <diggsey googlemail.com> writes:
On Monday, 27 May 2013 at 03:28:07 UTC, deadalnix wrote:
 On Monday, 27 May 2013 at 02:31:50 UTC, Jonathan M Davis wrote:
 On Monday, May 27, 2013 04:24:51 Diggory wrote:
 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.

Well, changing TypeTuple to only accept types _will_ break code. It gets used quite heavily with foreach to get a static foreach, and that can involve using expressions instead of types. Anyone using TypeTuple heavily knows what it can do and will probably have used it for expressions at some point. It wouldn't surprise me in the least if it's already done in Phobos, and there's no way to know how much it is or isn't done elsewhere.

Granted that nobody understand them, it is fair to say it should be changed.

In case people agree: https://github.com/D-Programming-Language/phobos/pull/1309
May 27 2013
prev sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Monday, 27 May 2013 at 09:25:14 UTC, Diggory wrote:
 Granted that nobody understand them, it is fair to say it 
 should be changed.

In case people agree: https://github.com/D-Programming-Language/phobos/pull/1309

I'm all for it. Thank you.
May 27 2013