DIP32: Uniform tuple syntax

kenji hara k.hara.pg at gmail.com
Fri Mar 29 08:11:47 PDT 2013


2013/3/29 bearophile <bearophileHUGS at lycos.com>

> One handy tuple syntax in Haskell allows you to name both the items of a
> tuple and it whole:
>
> void foo(t2@{int a, string b}) {
>    // here a and b are tuple items and t2 is the whole tuple.
> }
> auto t1@{x, y} = {10, "hi"};
> foo(t1);
>

It will introduce a kind of "reference variable" to D.

auto t1@{x, y} = {10, "hi"};
assert(&t1[0] == &x);
// t1[0] and x may refer same address on stack.

Such case, you can repeat pack and unpack.

void foo({int a, string b}) {
   // auto t2 = {a, b};  // make tuple by copy, or
   // {a, b} = {1, 2};    // make pack and use it immediately
}
auto {x, y} = {10, "hi"};  foo({x, y});


> auto tup = {};  // zero-element tuple (Syntax meaning will be changed!)
>
> Nullary tuples are not that useful in D. Scala doesn't even have a short
> literal for them.
>
> So a longer syntax like this is acceptable:
>
> auto tup = Tuple();
>

This is for the consistency of language elements.
If you want to zero-parameter lambda, you can write like follows.

auto fn = (){};
auto fn = {;};


> - - - - - - - - - - - -
>
> This is nice, so we are merging tuple types with tuples, this will
> simplify D language:
>
> // declare tuple value by using explicit tuple type
> {int, string} tup = {1, "hi"};
>
>  alias TL = {int, string[], double[string]};  // types
>
>
> But one thing to remember in the document is that here T1 and T2 are
> different, because your tuples do not auto-flatten as TypeTuples currently
> do:
>
> alias T1 = {float, double, real};
> alias T2 = {float, double, {real}};
>

It would need more description. I'll explain about that.

- - - - - - - - - - - -
>
> foreach (Float; {float, double, real}) { ... }
>
> I think you meant to put a variable name there.
>

Float is the iterated type.


> - - - - - - - - - - - -
>
>     {1}         // one-element tuple
>
> I presume this too will be accepted as 1-tuple:
>
>     {1,}
>

Currently D allows redundant commas in some places.
void foo(int x, int y,) {}
enum E { a = 1, b = 2, }
auto arr = [1,2,3,];

So, compiler would accept following tuples.

auto tup = {1,};
auto tup = {1,"hi",};


> - - - - - - - - - - - -
>
> {c, $} = tup;   // Rewritten as: c = tup[0];
>
> $ is used for array lengths, so it's not so good to overload it to mean
> "don't care" too.
>
> Alternative syntaxes:
>
> {c, $_} = tup;
> {c, @} = tup;
> {c, @_} = tup;
> {c, $$} = tup;
> {c, {}} = tup;
> {c, {_}} = tup;
> {c, $~} = tup;
> {c, @~= tup;
> etc.
>

Placeholder token is debatable.


> - - - - - - - - - - - -
>
>
> if (auto {1, y} = tup) {
>     // If the first element of tup (tup[0]) is equal to 1,
>     // y captures the second element of tup (tup[1]).
> }
>
>
> I suggest to leave that pattern matching plus conditional to a future
> refinement of tuple implementation (a second stage. And remove it from this
> first stage proposal. So I suggest to split your proposal in two successive
> proposals). It seems handy, but D programmers need some time to go there.
>

For complex tuple unpacking requires the part of pattern matching.

auto tup = {1, {2,3,4,5,6}}
auto {x, {$, y, ...}} = tup;   // makes nested tuple pattern for unpacking
assert(x == 1);
assert(y == 3);

So I'd like to keep one DIP.


> - - - - - - - - - - - -
>
> switch (tup) {
>     case {1, 2}:
>     case {$, 2}:
>     case {1, x}:    // capture tup[1] into 'x' when tup[0] == 1
>     default:        // same as {...}
> }
>
>
> What's quite important here is the "final switch". D has to make sure you
> are considering all possible cases.
>
> - - - - - - - - - - - -
>
> I suggest to leave this to the second stage, and remove it from this
> proposal:
>
> auto tup = {1, "hi", 3.14, [1,2,3]};
> if (auto {1, "hi", ...} = tup) {}
>
> - - - - - - - - - - - -
>
> "will" is written badly:
>
>
> // If the first element of coord is equal to 1 (== x), 'then' statement
> wil be evaluated.
>

Will fix.


> - - - - - - - - - - - -
>
> I think this is the third thing to leave to the second stage:
>
> int x = 1;
> if (auto {$x, y} = coord) { ... }
>
> - - - - - - - - - - - -
>
> This is nice:
>
> if (auto {x, y} = coord[]) {}   // same, explicitly expands fields
>
> - - - - - - - - - - - -
>
> This is handy and it's vaguely present in Python3, but I suggest to leave
> this (4th thing) to the second stage:
>
> if (auto {num, msg, ...} = tup) {}      // ok, `...` matches to
> zero-elements.
>

Kenji Hara
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20130330/c63629f8/attachment-0001.html>


More information about the Digitalmars-d mailing list