Tuple literal syntax + Tuple assignment

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu Oct 7 08:30:05 PDT 2010


On 10/7/10 7:09 CDT, bearophile wrote:
> In the two threads (that are a single thread) most of the things I've seen are bad/wrong.
>
> I have discussed about Tuples several times in the D newsgroup and in Bugzilla. Please don't ignore all my work.
>
> Before designing tuple syntax you must decide what the purpose of D tuples is. Then you have to solve the design problems, and avoid all (or most) corner cases. In this discussion it's useful to have a certain experience of languages that use tuples often, as Python and others.

Good point.

> Tuples have some purposes:
> - Python, Go and other languages show that it's handy to allow functions to return multiple values, this means a tuple.
> - A handy tuple unpacking is useful at the calling point of a function that returns multiple return values.
> - Tuples are also useful as quick-and-dirty structs, to sort items in a different order, etc.
>
> It's useful to use [] to access tuple items, to slice tuples, concat them. It's useful for tuples to have a good textual representation, to be comparable lexicographically and to be hashable.

Yes, excellent. Now I realize we don't have hash for tuples just yet.

> Another design decision is if tuples have a nominative or structural type, this problem comes out in this bug report:
> http://d.puremagic.com/issues/show_bug.cgi?id=4128
>
> In my opinion it's good for a built-in D tuple to be a structural type. This also means you are allowed to perform an == among two tuples of different length (the result is known statically to be always false). I assume that D tuples know their length at compile-time.

Yah, I think tuples are the quintessential structural types. I think, 
however, that "==" shouldn't test for prefix (that would be 
_sub_typing). This is because slicing takes care of it. For example:

Tuple!(int, int, int) point3d;
Tuple!(int, int) point2d;
point2d == point3d; // doesn't compile
point2d == point3d[0 .. point2d.length]; // compiles

> Another significant problem is about naming things, currently the situation is a mess:
> http://www.digitalmars.com/d/archives/digitalmars/D/Tuple_TypeTuple_tupleof_etc_113005.html
> http://d.puremagic.com/issues/show_bug.cgi?id=4113
> In the end I have suggested to name "record" the typecons tuples, and "tuple" the typetuples.

I think we're in good shape with Tuple and tuple. The "other" tuples 
deserve an odder name.

> I have several bug reports and enhancement requests about tuples, please take them into account:
>
> http://d.puremagic.com/issues/show_bug.cgi?id=4577
> http://d.puremagic.com/issues/show_bug.cgi?id=4582
> http://d.puremagic.com/issues/show_bug.cgi?id=4591
> http://d.puremagic.com/issues/show_bug.cgi?id=4666
> http://d.puremagic.com/issues/show_bug.cgi?id=4846

Nice. I like at least some of each.

> Walter:
>
>> A lot of it foundered on what the syntax for tuple literals should be. The top
>> of the list is simply enclosing them in ( ).
>
> This is a bad idea. It has caused troubles in Python because of the singleton syntax (tuple with 1 item).

During our conversation I conveyed my suspicion that that one corner 
case (which is very often encountered in generic code) will inevitably 
do this whole thing in, but he was quick to gloss over the issues. I'd 
be glad to have experience with Python save us some sweat. Do you have 
any links to discussions regarding the matter?

> One solution is to use a special unambigous delimiter to denote tuples, like (a similar solution is used in the Fortress language):
>
> (||)
> (|1|)
> (|1, 2|)
> (|1, 2, 3|)
> (|1, 2, 3, 4|)

Yup, the banana notation.

> Otherwise a good solution is to use a name:
>
> record()
> record(1)
> record(1, 2)
> record(1, 2, 3)
> record(1, 2, 3, 4)
>
> I prefer the record() solution, but the first solution too acceptable.

How about the shorter "tuple"? Wait, it's already there :o).

>> Finally, I got to thinking, why not just make it a special case:
>>
>>    ( ) == tuple
>>    (a) == parenthesized expression
>
> This is not acceptable. No special cases, please. D has already a ton of special cases.
> Python solves this with the (1,) syntax, but it's not nice, it's error-prone, and it confuses newbies.

Evidence please?

>> If expr represents a tuple, we (Andrei and I) were thinking about the syntax:
>>
>>       auto (a, b, c, d) = expr;
>
> On this topic I have this enhancement request:
> http://d.puremagic.com/issues/show_bug.cgi?id=4579
>
>
>> The Lithpers among you will notice that this essentially provides a handy
>> car,cdr shortcut for tuples and arrays:
>>
>>       auto (car, cdr) = expr;
>
> This is bad, it's not explicit enough. If you want to support this semantics then the syntax has to show what you mean. Python uses a * to denote "grab the whole tail". In D you may use something else, others have suggested tree points, this works with dynamic arrays too:
>
> auto (car, cdr...) = expr;

Nice.

> Regarding field names for tuples, I have used Python and I like the optional names of D tuples (records). In some situations you don't need names, but in other situations field names are handy and help avoid bugs. In Python code that processes and uses tuples contains too many [0] [1] [2] etc that aren't readable and are bug-prone.

Evidence please?

> But a good management of such names asks for the names to not change the type of the tuple, this is why I talk about structural typing for records.

Makes sense.


Andrei


More information about the Digitalmars-d mailing list