The tuple notion comes from math where it means a fixed sequence of related but maybe completely different entities. In dynamic languages tuples are fixed-length lists of values of arbitrary types. The closest analogy in c-family languages would be an anonymous struct. In D things are somewhat more complicated though.
In D, tuple is strictly a compile-time construct. It is a fixed-length list of types, compile-time expressions, or symbols, in any combination. There are two obvious and useful tuple sub-classes: type tuples consisting only of types, and expression tuples consisting only of expressions. These are mentioned in documentation and seem to be purely conventional.
But there’s more to that. If you have a type tuple you can declare a variable of that type. I’m not sure if this is documented anywhere. This variable will be perfectly runtime. It will have tuple type even though documentation asserts that tuples are not types. You’ll be able to change value of this variable, either as a whole by assigning a compatible expression tuple or another such variable to it, or by modifying individual components by indexing them. Still such a variable will display some tuple characteristics like flattening when passed as a function argument.
I will call such variables tuple variables, and values in them tuple values. They’re distinct from tuples as such. This is why I don’t like naming of std.typetuple.TypeTuple and std.typecons.Tuple: they’re both misnomers. TypeTuple is actually a generic tuple constructor which allows to create any tuple supported by compiler. The Tuple is an anonymous struct constructor which contains a tuple variable as an alternative means to access struct fields, but is otherwise not a tuple at all.
There are several things required so that the language feels like it supports tuples:
- Sugar for type tuple construction
- Sugar for tuple value construction: tuple literals
- Parallel assignment
I agree with others in the community that reusing the comma operator for that would be perfect. I think it’s possible:
- Let comma operator result be a tuple instead of an expression after the last comma
- Allow types in place of expressions
- Let semantic analyzer discard mixed tuple literals as invalid
- Treat type tuples as regular types, and expression tuples as tuple value literals
- Support C: when a tuple value is cast to a scalar type, replace tuple value with its last element
I can see two for now:
- Weird tuple to scalar cast
- Tuple flattening may conflict with C compatibility:
foo((a, b, c));
This code means foo(c) in C but foo(a, b, c) in this proposal
Point 1 can be dealt with: either discarded, or such a conversion made illegal which I don’t think will hurt many. But point 2 may be a real show-stopper.