Tuple literal syntax + Tuple assignment

bearophile bearophileHUGS at lycos.com
Thu Oct 7 15:34:52 PDT 2010


Andrei:

Another possible useful feature for tuples is to unpack them in foreach too:

import std.algorithm, std.stdio, std.range;
void main() {
    foreach (p; zip([1, 2, 3], "abcd"))
        writeln(p[0], " ", p[1]);
    writeln();
    foreach ((a, b); zip([1, 2, 3], "abcd"))
        writeln(a, " ", b);
}


A related handy feature, present in Python2 is destructuring (unpacking) in function signature:

- upacking syntax, pattern matching

>>> def foo((x, y), z): print y
...
>>> foo("ab", 2)
b


This allows you to do many things, like define a lambda function that swaps items of the given 2-tuple:

lambda (seq,freq): (freq,seq)


Python3 has removed this automatic unpacking (not because that feature is not handy, but mostly to simplify the source code of CPython!), and it has added the unpaking syntax for n items:
first, second, *tail = (1, 2, 3, 4)


Recently I have written something about support for slicing tuples and similar compile-time sized structures:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=117890


>I think, however, that "==" shouldn't test for prefix<

You are right, that's an error of mine caused by thinking about tuple lengths as immutable but known at run-time only, as in Python. It's better to disallow at compile time the opEquals of tuples of different length.


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

I don't love the name "record" and I agree that "tuple" is OK. But if in the language there is a built-in attribute named "tupleof" that returns something that's not a tuple, then... it's not nice. This is why I have suggested to name tuples the built-in ones and record() the library+SyntaxSugar defined ones. Naming them record is not terrible, in my opinion.
 

>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?<

>Evidence please?<

There are endless questions and discussions in Python newsgroups about the syntax of Python tuples, you may find several of them in comp.lang.python. Some of them:

http://groups.google.com/group/comp.lang.python/browse_thread/thread/673344303e27ed6/

http://groups.google.com/group/comp.lang.python/browse_thread/thread/699ec8cb75c7cbda/088aee81cdca92ec?lnk=gst&q=%22tuple+syntax%22#088aee81cdca92ec


Python programmers eventually always learn to manage them correctly, but many other Python features don't generate that many discussions, this means their syntax is not as clean and simple as many other Python features.

I've taught Python, and I've seen that I need several minutes to teach how tuples are in Python. While such problems are not present when I explain the Python list syntax, that is more clean.

In Python lists are arrays dynamic on the right. You need to put the items inside square brackets. So if there's nothing between them, you have an empty list, []. This is simple.

A Python tuple is generally not defined by the ( ) . It is defined by the comma.

So this is a tuple of 3 items:
a = (1, 2, 3)
But () is not necessary, so this too is the same tuple:
a = 1, 2, 3

So (1) is not a 1-tuple, you need a comma:
(1,)
I've seen cases where programmers forget or don't see that comma.

And there's another special case, the empty tuple. This is the only case where the ( ) are actually part of the tuple syntax, and necessary:

()

There's another way to define an empty tuple, using the type:
tuple()

There are also some corner cases, like this one present in Python2.6 still:

>>> (a,) = (1,)
>>> () = ()
  File "<stdin>", line 1
SyntaxError: can't assign to ()


In the end all this doesn't cause frequent bugs in Python programs, but it's not clean nor elegant, especially if you see this in the context of a language as clean as Python.


> Yup, the banana notation.

It's clean, short, unambiguous, and I think it has no corner cases, so it's not terrible. This is why Fortress uses similar syntax. It may be just sugar for the Tuple/Record of typecons.


>> auto (car, cdr...) = expr;

> Nice.

Not invented by me :-)


>>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?<

I am not sure what kind of evidence you may want. The need to give a name to tuple fields was so strong that Hettinger has added them as collections.namedtuple, this was a early Python implementation (later translated to C):
http://code.activestate.com/recipes/500261-named-tuples/

If you have a Python tuple, and you unpack items, you may confuse [0] with [1] much more often than field names as "key" and "value". Names are also more readable, when you later want to read the code.

Ask if you want more comments about this last point.

----------------------

>D's built in type tuples (those used with TypeTuple) are weird.<
>They are terrible, awful, despiteful.<

I'd like to have a single kind of tuples in D2, but Walter has explained that you can't return the built-in tuples because of stack alignments matters.


>My suggestion is that we deprecate TypeTuple and we call it AliasTuple because that's really what it is - it's a tuple of stuff that can be passed in as an alias parameter.<

The name "AliasTuple" is surely better than "TypeTuple", because they aren't tuple of types.

But problems the simpler solution is to call "Record" the (mostly) library defined ones and Tuples the built-in ones.

----------------------

The quickIn operator may just reuire the presence of the @complexity(O.sublinear) attribute at the function that implements the "in" operator :-)

----------------------

More than three years ago I have asked to see for some new features in D1, in the meantime several of them have being added to D2. In the meantime some of my requests have changed, but good enough tuples was one of those original feature requests of mine.

There are only few missing things that I think are worth adding: integral overflows, named function arguments at calling point, better unit testing, "old" for Contracts, good user-defined attributes for user extensions of the type system, some support for slots & signals to create GUIs. In theory all of them are additive changes (except few tiny changes already in Bugzilla), but integral overflows are better implemented sooner than later because I think retrofitting Phobos for overflow-awareness is not easy.

Bye,
bearophile


More information about the Digitalmars-d mailing list