DIP19: Remove comma operator from D and provision better syntactic support for tuples
bearophile
bearophileHUGS at lycos.com
Sun Sep 23 15:11:44 PDT 2012
This is a complex topic, and in this post I am not able to
discuss everything that needs to be discussed. So I will discuss
only part of the story.
First: tuples are important enough. I think they should be
built-in in a modern language, but maybe having them as
half-built-in will be enough in D. Currently in D we have
(deprecated) built-in complex numbers that I use only once in a
while, and half-usable library defined tuples that I use all the
time.
Second: removing comma operator from D has some advantages
unrelated to tuple syntax. Even disallowing bad looking C-like
code that uses commas is an improvement by itself (but maybe it's
not a big enough improvement...).
Third: replacing the packing syntax tuple(x,y) with (x,y) is nice
and maybe even expected in a partially functional language as D,
but that's _not_ going to improve D usability a lot. What I am
asking for is different: I'd like D tuples to support handy
unpacking syntax:
1) In function signatures;
2) In foreach;
3) At assignment points;
4) In switch cases.
Note: in the examples below I have used the tuple(x,y) syntax for
simplicity, feel free to replace it with a shorter (x,y) syntax
if you want.
---------------------------
1) This tuple unpacking use case is important, and it's not what
you argue against in the DIP:
int f(tuple(int x, int y)) { return x + y; }
auto pairs = zip([10, 20], [2, 3]);
map!f(pairs)
This is different from what you are arguing against because this
"f" is not accepting two normal ints, it accepts a tuple made of
two ints, and names them "x" and "y" on the fly.
---------------------------
2)
auto pairs = zip([10, 20], [2, 3]).array();
foreach (i, tuple(x, y); pairs) {}
---------------------------
3) This is probably the most common use case:
auto foo() { return tuple(10, 20); }
auto tuple(x, y) = foo(); // bad syntax
auto (x, y) = foo(); // better syntax
void main() {
auto a = tuple(1, 2);
auto tuple(x1, x2) = a; // bad syntax
auto (y1, y2) = a; // better syntax
}
---------------------------
4) This looks simple, but allows things like using BigInt in
switch cases, implementing a very simple but quite handy
pattern-matching, etc:
auto v = tuple(10, 20);
final switch (v) {
case tuple(5, y): { x in scope... } break; // y is not a
global
case tuple(x, y): { ... } break; // this covers all cases
}
---------------------------
There are other usage patterns that are handy, but in my opinion
the four I have shown here are the most commonly useful ones. See
also Bugzilla issues 6365 and 6367, they shows some other cases
and ideas and problems.
---------------------------
Tuple singletons: using (1,) as in Python is acceptable. using
(1) is not acceptable in my opinion, too much dangerous. tuple(1)
is also acceptable, it's longer, but it's not commonly used, so
it's OK.
Empty tuples: the (,) syntax proposed in the DIP is not nice, it
seems to have one invisible item, but maybe it's acceptable.
tuple() is also acceptable, it's longer, but it's not commonly
used, so it's OK.
In the end tuples with 0 and 1 items are sometimes useful, but
they are not nearly as useful as supporting well tuples with 2 or
more items. Scala language agrees with this.
---------------------------
Tuple slicing: it's not a fundamental operation, but it's nice to
try to make it work correctly :-) I think not even Haskell does
this well.
---------------------------
Summary:
- I think (1,2) is nicer and better than tuple(1,2), and I'd like
to have such syntax, but it's not a large improvement and it's
not what I am asking for now (less priority).
- Supporting tuples with 0 and 1 items is sometimes handy but I
think it's not essential.
- On the other hand syntax to unpack/destructure tuples in many
situations is important for allowing a proper and handy use of
tuples in D.
Bye,
bearophile
More information about the Digitalmars-d
mailing list