www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP32: Uniform tuple syntax

reply kenji hara <k.hara.pg gmail.com> writes:
--f46d044481314d244004d90c778e
Content-Type: text/plain; charset=UTF-8

http://wiki.dlang.org/DIP32

Kenji Hara

--f46d044481314d244004d90c778e
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><a href=3D"http://wiki.dlang.org/DIP32">http://wiki.dlang.=
org/DIP32</a>=C2=A0<br><div><br></div><div>Kenji Hara</div></div>

--f46d044481314d244004d90c778e--
Mar 29 2013
next sibling parent "Dicebot" <m.strashun gmail.com> writes:
On Friday, 29 March 2013 at 08:58:06 UTC, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

Can't tell at the first read about possible issues, but conceptually - love it, fits nicely.
Mar 29 2013
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
29-Mar-2013 12:57, kenji hara пишет:
 http://wiki.dlang.org/DIP32

 Kenji Hara

A few typos like: {c, $} = tup; // Rewritten as: a = tup[0]; where it should be //Rewritten as c = tup[0]; About swapping values by tuple assignment. Why not simply make this work: {x, y} = {y, x} By lowering {x, y} = {y, x}; to auto temp0 = y; auto temp1 = x; x = temp0; y = temp1; And let the compiler do value propagation to remove the extra temp0. Another note - is there any way to extend this notation to common structs other then .tupleof ? I think we may hopefully extended it later towards struct destructruing a-la EcmaScript 6, see http://wiki.ecmascript.org/doku.php?id=harmony:destructuring All in all it's a great proposal, I'm loving it. -- Dmitry Olshansky
Mar 29 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--e89a8f64663ff1083004d90d5a7f
Content-Type: text/plain; charset=UTF-8

2013/3/29 Dmitry Olshansky <dmitry.olsh gmail.com>

 A few typos like:
 {c, $} = tup;   // Rewritten as: a = tup[0];
 where it should be //Rewritten as c = tup[0];

Thanks. Fixed.
 About swapping values by tuple assignment.

 Why not simply make this work:
 {x, y} = {y, x}

 By lowering
 {x, y}  = {y, x};
 to
 auto temp0 = y;
 auto temp1 = x;
 x = temp0;
 y = temp1;

 And let the compiler do value propagation to remove the extra temp0.

Because it already exists. template Seq(T...) { alias Seq = T; } void main() { int x = 1, y = 2; Seq!(x, y) = Seq!(y, x); // tuple assigmnent assert(x == 2); assert(y == 2); } Another note - is there any way to extend this notation to common structs
 other then .tupleof ? I think we may hopefully extended it later towards
 struct destructruing a-la EcmaScript 6, see

 http://wiki.ecmascript.org/**doku.php?id=harmony:**destructuring<http://wiki.ecmascript.org/doku.php?id=harmony:destructuring>

Hmm, interesting. I'll see it later. Kenji Hara --e89a8f64663ff1083004d90d5a7f Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><br><div class=3D"gmail_extra"><div class=3D"gmail_quote">= 2013/3/29 Dmitry Olshansky <span dir=3D"ltr">&lt;<a href=3D"mailto:dmitry.o= lsh gmail.com" target=3D"_blank">dmitry.olsh gmail.com</a>&gt;</span><br><b= lockquote class=3D"gmail_quote" style=3D"margin-top:0px;margin-right:0px;ma= rgin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:r= gb(204,204,204);border-left-style:solid;padding-left:1ex"> A few typos like:<br> {c, $} =3D tup; =C2=A0 // Rewritten as: a =3D tup[0];<br> where it should be //Rewritten as c =3D tup[0];<br></blockquote><div><br></= div><div>Thanks. Fixed.=C2=A0</div><div>=C2=A0</div><blockquote class=3D"gm= ail_quote" style=3D"margin-top:0px;margin-right:0px;margin-bottom:0px;margi= n-left:0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);borde= r-left-style:solid;padding-left:1ex"> About swapping values by tuple assignment.<br> <br> Why not simply make this work:<br> {x, y} =3D {y, x}<br> <br> By lowering<br> {x, y} =C2=A0=3D {y, x};<br> to<br> auto temp0 =3D y;<br> auto temp1 =3D x;<br> x =3D temp0;<br> y =3D temp1;<br> <br> And let the compiler do value propagation to remove the extra temp0.<br></b= lockquote><div><br></div><div>Because it already exists.<br></div><div><div=
<br></div><div>template Seq(T...) { alias Seq =3D T; }</div><div>void main=

<div>{</div><div>=C2=A0 =C2=A0 int x =3D 1, y =3D 2;</div><div>=C2=A0 =C2= =A0 Seq!(x, y) =3D Seq!(y, x); =C2=A0 =C2=A0// tuple assigmnent</div><div>= =C2=A0 =C2=A0 assert(x =3D=3D 2);</div><div>=C2=A0 =C2=A0 assert(y =3D=3D 2= );</div><div>}</div></div><div><br></div><blockquote class=3D"gmail_quote" = style=3D"margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8e= x;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-styl= e:solid;padding-left:1ex"> Another note - is there any way to extend this notation to common structs o= ther then .tupleof ? I think we may hopefully extended it later towards str= uct destructruing a-la EcmaScript 6, see<br> <br> <a href=3D"http://wiki.ecmascript.org/doku.php?id=3Dharmony:destructuring" = target=3D"_blank">http://wiki.ecmascript.org/<u></u>doku.php?id=3Dharmony:<= u></u>destructuring</a></blockquote><div><br></div><div>Hmm, interesting. I= &#39;ll see it later.</div> <div>=C2=A0</div><div>Kenji Hara</div></div><br></div></div> --e89a8f64663ff1083004d90d5a7f--
Mar 29 2013
prev sibling next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
My first thought when I saw {} was json. This is getting a little 
further away from tuples, but would it be hard to add named 
fields to this too like json:

auto a = {"foo":12, "bar":"twelve"};

int a_foo = a.foo;
string a_bar = a[1];


The std.typecons Tuple!() can do this kind of thing too.
Mar 29 2013
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 01:49 PM, Adam D. Ruppe wrote:
 My first thought when I saw {} was json. This is getting a little
 further away from tuples, but would it be hard to add named fields to
 this too like json:

 auto a = {"foo":12, "bar":"twelve"};

 int a_foo = a.foo;
 string a_bar = a[1];


 The std.typecons Tuple!() can do this kind of thing too.

Remove the quotes and it looks like a struct literal. I think if named fields are allowed, it should look as follows: auto a = {foo: 12, bar: "twelve"};
Mar 29 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-03-29 14:26, Timon Gehr wrote:

 Remove the quotes and it looks like a struct literal.

 I think if named fields are allowed, it should look as follows:

 auto a = {foo: 12, bar: "twelve"};

I agree. -- /Jacob Carlborg
Mar 29 2013
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2013-03-29 13:49, Adam D. Ruppe wrote:
 My first thought when I saw {} was json. This is getting a little
 further away from tuples, but would it be hard to add named fields to
 this too like json:

 auto a = {"foo":12, "bar":"twelve"};

 int a_foo = a.foo;
 string a_bar = a[1];

I had a proposal of anonymous structs that is similar to this: http://forum.dlang.org/thread/kfbnuc$1cro$1 digitalmars.com -- /Jacob Carlborg
Mar 29 2013
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 http://wiki.dlang.org/DIP32

Thank you Kenji for working on this :-) Some comments on your proposal: - - - - - - - - - - - -
 Use braces and commas. Inside tuple literal, ; never appears. 
 So it will not be confused with lambdas and ScopeStatements.<

This is true. On the other hand it's not too much hard to forget a ; or to not see it by mistake. So please let's think well about this important design decision. - - - - - - - - - - - - I presume this will be valid code: auto tup = {10, "hi", 3.14}; assert(tup[0..2] == {10, "hi"}); - - - - - - - - - - - - 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); - - - - - - - - - - - - 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 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}}; - - - - - - - - - - - - foreach (Float; {float, double, real}) { ... } I think you meant to put a variable name there. - - - - - - - - - - - - {1} // one-element tuple I presume this too will be accepted as 1-tuple: {1,} - - - - - - - - - - - - {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. - - - - - - - - - - - - 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. - - - - - - - - - - - - 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. - - - - - - - - - - - - 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. - - - - - - - - - - - - Bye, bearophile
Mar 29 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 02:17 PM, Simen Kjærås wrote:
 On Fri, 29 Mar 2013 13:56:08 +0100, bearophile
 <bearophileHUGS lycos.com> wrote:

 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);

I suggest instead this syntax: auto {x, y} t1 = {10, "hi"}; It's closer to regular D syntax. ...

It is already taken and equivalent to: {x, y} t1 = {10, "hi"};
Mar 29 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 01:56 PM, bearophile wrote:
 kenji hara:

 ...
 Use braces and commas. Inside tuple literal, ; never appears. So it
 will not be confused with lambdas and ScopeStatements.<

This is true. ...

It is false.
Mar 29 2013
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 4/6/13 4:10 AM, bearophile wrote:
 Zach the Mystic:

 Not disagreeing, but you had mentioned nullable types before, and I
 was wondering what they might look like also. Have you made an
 enhancement for these I could examine?

I opened this: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Part of the syntax is: T? means T nullable T = means not nullable. But that ER is a confused mess, and in the meantime the disable was introduced. Now the probability of such nullable syntax+semantics to be introduced in D is very low, so probably I will close down that ER. Bye, bearophile

I think it's safe to close it. Nullable types have not enjoyed a lot of appreciation in C#. Andrei
Apr 06 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Adam D. Ruppe:

 auto a = {"foo":12, "bar":"twelve"};

 int a_foo = a.foo;
 string a_bar = a[1];


 The std.typecons Tuple!() can do this kind of thing too.

I think Tuple!() has them mostly because there is no handy syntax to unpack them. Tuples with field names are records. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 {c, {}} = tup;

This can't be used, because having an empty tuple as second tuple item is valid.
 {c,  ~= tup;

That was: {c, ~} tup; Bye, bearophile
Mar 29 2013
prev sibling next sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Fri, 29 Mar 2013 13:56:08 +0100, bearophile <bearophileHUGS lycos.com>  
wrote:

 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);

I suggest instead this syntax: auto {x, y} t1 = {10, "hi"}; It's closer to regular D syntax.
 foreach (Float; {float, double, real}) { ... }

 I think you meant to put a variable name there.

foreach (Type; {float, double, real}) { ... } See it now?
 - - - - - - - - - - - -

 {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.

... has been introduced to match zero or more elements for pattern matching already. I see no reason not to use ... for this. -- Simen
Mar 29 2013
prev sibling next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 09:57 AM, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

Looks quite nice. I especially like the {a, b} => ... thing. I think, however, that there are a handful serious flaws that need to be addressed: 0 "Inside tuple literal, ; never appears." {{;}} // a tuple not matching your specification {{if(foo()){}}} // a non-tuple matching your specification 1 "Note: Cannot swap values by tuple assignment." IMO a no-go. The syntax is too accessible to introduce this kind of pitfall. 2 "// Error: cannnot use $ inside a function literal" That's a DMD-ism presumably stemming from laziness during "fixing" of an ICE/wrong code bug or something. I'd hate to carry this over to the spec. Don't rely on it. The disambiguation is arbitrary, but may be necessary. (It's not like it is a case actually occurring in real code.) 3 Unpacking / pattern matching is underspecified. - Do patterns nest? - Which right-hand sides are allowed with which semantics? - Which left-hand sides are allowed with which semantics? eg, what about: ref int foo() { ... } { foo(), foo() } = {1, 2}; 4 There is no way to capture the part matched by "..." 5 .expand (or similar) property is missing. 6 Relation to {a: 2, b: 3}-style struct literals not explained. 7 Tuple unpacking for template parameters not mentioned. Is there a migration path for Phobos tuples planned? Eg. template Tuple(T...){ alias Tuple = {T}; } (field spec parsing left out for illustration)
Mar 29 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 02:25 PM, bearophile wrote:
 Timon Gehr:

 4 There is no way to capture the part matched by "..."

I have suggested to move the ... syntax to a Stage2, a different DEP.
 5 .expand (or similar) property is missing.

I think Kenji has suggested to use a trailing [] for that. ...

No, please. Slicing should not auto-expand. Leading to: 8 Slicing operations on tuples missing.
Mar 29 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 02:20 PM, Timon Gehr wrote:
 ...

 0 "Inside tuple literal, ; never appears."
    {{;}}           // a tuple not matching your specification
    {{if(foo()){}}} // a non-tuple matching your specification
 ...

The outer { } are not necessary in order to make the point: {if(foo()){}}
Mar 29 2013
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 04:32 PM, kenji hara wrote:
 2013/3/29 Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>>

     Looks quite nice. I especially like the {a, b} => ... thing.

     I think, however, that there are a handful serious flaws that need
     to be addressed:

     0 "Inside tuple literal, ; never appears."
        {{;}}           // a tuple not matching your specification


 It will be parsed as:
 {     // tuple braces

It contains ';', therefore the DIP says it is a function literal brace.
      {;}   // function literal braces
 }

        {{if(foo()){}}} // a non-tuple matching your specification


 {    // tuple braces
      {    // function literal braces

There is no ';', therefore the DIP says it is a tuple brace.
          if (foo()){}   // "if" always appears in statement scope
      }
 }

I know how it _should_ be. The DIP contradicts what you say.
     1 "Note: Cannot swap values by tuple assignment."
        IMO a no-go. The syntax is too accessible to introduce this kind of
        pitfall.


 Allowing value swap in tuple assignment will make language complex. I
 can't agree with it.

Quite obviously it is the other way round. There will be a never-ending flood of d.D.learn posts on the topic.
     2 "// Error: cannnot use $ inside a function literal"
        That's a DMD-ism presumably stemming from laziness during "fixing" of
        an ICE/wrong code bug or something. I'd hate to carry this over to
        the spec. Don't rely on it. The disambiguation is arbitrary, but may
        be necessary. (It's not like it is a case actually occurring in real
        code.)

     3 Unpacking / pattern matching is underspecified.
        - Do patterns nest?


 I think it should be allowed.

ok.
        - Which right-hand sides are allowed with which semantics?


 Whether it is a pattern or a tuple-literal, is distinguished by their
 appeared locations.

Obviously, but this statement is not related to my question. Valid right-hand sides seem to be at least tuples and expanded tuples (sequences). Anything else?
        - Which left-hand sides are allowed with which semantics?
          eg, what about:
            ref int foo() { ... }
            { foo(), foo() } = {1, 2};


 It will be lowered to:
 // { foo(), foo() } = {1, 2};
 foo() = 1;
 foo() = 2;

ok.
     4 There is no way to capture the part matched by "..."


 I think this should be allowed.

 auto {x, r...} = tup;
 // Lowered to:
 // auto x = tup[0];
 // auto r = tup[1..$]

 `...` is very consistent token for this purpose.

Questionable.
 template X(T...) {}
 alias x = X!(int, long);  // T captures {int, long}

Not really. T captures {int, long}.expand.
     5 .expand (or similar) property is missing.


 Use tup[]. It is already exists.

Slicing obviously shouldn't auto-expand. It's a shortcoming of the Phobos tuple introduced because static slicing cannot be overloaded.
     6 Relation to {a: 2, b: 3}-style struct literals not explained.


 I am skeptical of the necessity of tuple literal with named fields.

Sure, but you'd at least have to argue in the DIP that the parser can distinguish the two, and how.
     7 Tuple unpacking for template parameters not mentioned.


     Is there a migration path for Phobos tuples planned?

     Eg. template Tuple(T...){ alias Tuple = {T}; }
          (field spec parsing left out for illustration)

...

You have not answered the last two points.
Mar 29 2013
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 05:39 PM, kenji hara wrote:
 2013/3/30 bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.com>>

     kenji hara:


         I think it will become reasonable. If you really want re-packing
         tuple, you
         can use {tup[0..1]}. It's quite handy.


     This is a bad idea. It is not handy and it introduces a special
     case. Explicit is better than implicit.


 That is "explicit".  In D, opened tuple (currently it's generated from
 template parameters, e.g. std.typetuple.TypeTuple) and closed tuple
 (currently created by structs with alias tuple_field this; e.g.
 std.typecons.Tuple) are distinct. Slice operator always returns opened
 tuple.

Because of prior language limitations, not because it makes any sense! Current operator overloading limitations mandate that it is simply not possible to create a Phobos tuple with a sane slice operator.
 If tup[0..1] makes closed tuple implicitly, you cannot make new
 flattened tuple from other tuples.

 auto x = {1,"hi"};
 auto y = {[1,2], S(1)};
 auto tup1 = {x[], y[]};   // creates {1,"hi", [1,2], S(1)}
 auto tup2 = {x, y};   // creates {{1,"hi"}, {[1,2], S(1)}}

 Under your semantics, it is impossible.
 ...

Certainly not. Creating opened tuples from closed ones is not an operation necessarily tied to slicing. Making an opened tuple should be an explicit operation on closed tuples. Slicing and opening are orthogonal operations. auto tup1 = {x.open, y.open}; // creates {1,"hi", [1,2], S(1)} auto tup2 = {x[0..2], y[]}; // creates {{1,"hi}, {[1,2], S(1)}} auto tup3 = {x[0..2].open, y[].open}; // creates {1,"hi", [1,2], S(1)}
Mar 29 2013
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/31/2013 08:20 PM, Kagamin wrote:
 On Friday, 29 March 2013 at 15:47:52 UTC, Timon Gehr wrote:
 template X(T...) {}
 alias x = X!(int, long);  // T captures {int, long}

Not really. T captures {int, long}.expand.

Should there be a difference?

Sure.
Mar 31 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Timon Gehr:

 4 There is no way to capture the part matched by "..."

I have suggested to move the ... syntax to a Stage2, a different DEP.
 5 .expand (or similar) property is missing.

I think Kenji has suggested to use a trailing [] for that. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Simen Kjærås:

 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);

I suggest instead this syntax: auto {x, y} t1 = {10, "hi"}; It's closer to regular D syntax.

But I'd like sometime to tie t1 to that {}, to help my eyes.
 {c, $_} = tup;
 {c,  } = tup;
 {c,  _} = tup;
 {c, $$} = tup;
 ...
 {c, {_}} = tup;
 {c, $~} = tup;
 ...
 etc.

... has been introduced to match zero or more elements for pattern matching already. I see no reason not to use ... for this.

Telling the language that there there is exactly one item to match on, that you don't care of, is important. The "..." syntax can't tell apart the case for zero, one, or more items. So "..." can't be enough here. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--089e0112c512e557a604d9117c7a
Content-Type: text/plain; charset=UTF-8

For tuple values with named fields, we need more thoughts about semantics.

alias MyPair = typeof({1, "hi"});
alias MyRecord = typeof({count:1, msg:"hi"});
static assert(is(MyPair == MyRecord));  // true or false?
static assert(is(MyPair  : MyRecord));  // true or false?
static assert(is(MyRecord  : MyPair));  // true or false?
alias MyStudent = typeof({num:1, name:"John"});
static assert(is(MyRecord == MyStudent));  // true or false?

Kenji Hara


2013/3/29 Adam D. Ruppe <destructionator gmail.com>

 My first thought when I saw {} was json. This is getting a little further
 away from tuples, but would it be hard to add named fields to this too like
 json:

 auto a = {"foo":12, "bar":"twelve"};

 int a_foo = a.foo;
 string a_bar = a[1];


 The std.typecons Tuple!() can do this kind of thing too.

--089e0112c512e557a604d9117c7a Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div>For tuple values with named fields, we need more thou= ghts about semantics.<br></div><div><br></div><div><div>alias MyPair =3D ty= peof({1, &quot;hi&quot;});</div><div>alias MyRecord =3D typeof({count:1, ms= g:&quot;hi&quot;});</div> <div>static assert(is(MyPair =3D=3D MyRecord)); =C2=A0// true or false?</di= v><div>static assert(is(MyPair =C2=A0: MyRecord)); =C2=A0// true or false?<= /div><div>static assert(is(MyRecord =C2=A0: MyPair)); =C2=A0// true or fals= e?</div><div>alias MyStudent =3D typeof({num:1, name:&quot;John&quot;});</d= iv> <div>static assert(is(MyRecord =3D=3D MyStudent)); =C2=A0// true or false?<= /div></div><div><br></div><div style>Kenji Hara</div><div class=3D"gmail_ex= tra"><br><br><div class=3D"gmail_quote">2013/3/29 Adam D. Ruppe <span dir= =3D"ltr">&lt;<a href=3D"mailto:destructionator gmail.com" target=3D"_blank"=
destructionator gmail.com</a>&gt;</span><br>

left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex">My first thought when I saw {} was json. This is getting a= little further away from tuples, but would it be hard to add named fields = to this too like json:<br> <br> auto a =3D {&quot;foo&quot;:12, &quot;bar&quot;:&quot;twelve&quot;};<br> <br> int a_foo =3D a.foo;<br> string a_bar =3D a[1];<br> <br> <br> The std.typecons Tuple!() can do this kind of thing too.<br> </blockquote></div><br></div></div> --089e0112c512e557a604d9117c7a--
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
On Friday, 29 March 2013 at 14:57:33 UTC, kenji hara wrote:
 For tuple values with named fields, we need more thoughts about 
 semantics.

Tuples with named fields are records. Once we have a unpacking syntax, the names become less needed. I suggest to leave field names to the Stage2. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Once tuples have a built-in syntax it becomes possible to add 
pairs/byPair to associative arrays:


auto aa = [1:2, 3:4];
{int, int}[] myPairs1 = aa.pairs;
foreach ({k, v}; myPairs1) {}
auto myPairs2 = aa.byPair;
foreach ({k, v}; myPairs2) {}

Bye,
bearophile
Mar 29 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--047d7b86db60a0167804d911b042
Content-Type: text/plain; charset=UTF-8

2013/3/29 bearophile <bearophileHUGS 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 --047d7b86db60a0167804d911b042 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">2013/3/29 bearophile <span dir=3D"ltr">&lt;<a href=3D"mail= to:bearophileHUGS lycos.com" target=3D"_blank">bearophileHUGS lycos.com</a>= &gt;</span><br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><block= quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w= idth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding= -left:1ex"> One handy tuple syntax in Haskell allows you to name both the items of a tu= ple and it whole:<br> <br>void foo(t2 {int a, string b}) {<br> =C2=A0 =C2=A0// here a and b are tuple items and t2 is the whole tuple.<br> }<br> auto t1 {x, y} =3D {10, &quot;hi&quot;};<br> foo(t1);<br></blockquote><div><br></div><div style>It will introduce a kind= of &quot;reference variable&quot; to D.</div><div style><br></div><div sty= le>auto t1 {x, y} =3D {10, &quot;hi&quot;};<br></div><div style>assert(&amp= ;t1[0] =3D=3D &amp;x);</div> <div style>// t1[0] and x may refer same address on stack.</div><div><br></= div><div style>Such case, you can repeat pack and unpack.</div><div>=C2=A0<= /div>void foo({int a, string b}) {</div><div class=3D"gmail_quote">=C2=A0 = =C2=A0// auto=C2=A0t2 =3D {a, b}; =C2=A0// make tuple by copy, or</div> <div class=3D"gmail_quote">=C2=A0 =C2=A0// {a, b} =3D {1, 2}; =C2=A0 =C2=A0= // make pack and use it immediately<br>}<br><div>auto {x, y} =3D {10, &quot= ;hi&quot;}; =C2=A0foo({x, y});</div><div>=C2=A0=C2=A0</div><blockquote clas= s=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;b= order-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"=

auto tup =3D {}; =C2=A0// zero-element tuple (Syntax meaning will be change= d!)<br> <br>Nullary tuples are not that useful in D. Scala doesn&#39;t even have a = short literal for them.<br> <br> So a longer syntax like this is acceptable:<br> <br> auto tup =3D Tuple();<br></blockquote><div><br></div><div style>This is for= the consistency of language elements.</div><div style>If you want to zero-= parameter lambda, you can write like follows.</div><div style><br></div> <div style>auto fn =3D (){};<br></div><div style>auto fn =3D {;};<br></div>= <div style>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margi= n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204= );border-left-style:solid;padding-left:1ex"> - - - - - - - - - - - -<br> <br> This is nice, so we are merging tuple types with tuples, this will simplify= D language:<br> <br> // declare tuple value by using explicit tuple type<br> {int, string} tup =3D {1, &quot;hi&quot;};<br> <br> =C2=A0alias TL =3D {int, string[], double[string]}; =C2=A0// types<br> <br> <br> But one thing to remember in the document is that here T1 and T2 are differ= ent, because your tuples do not auto-flatten as TypeTuples currently do:<br=

alias T1 =3D {float, double, real};<br> alias T2 =3D {float, double, {real}};<br></blockquote><div><br></div><div s= tyle>It would need more description. I&#39;ll explain about that.=C2=A0</di= v><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px = 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l= eft-style:solid;padding-left:1ex"> - - - - - - - - - - - -<br> <br> foreach (Float; {float, double, real}) { ... }<br> <br> I think you meant to put a variable name there.<br></blockquote><div><br></= div><div style>Float is the iterated type.</div><div>=C2=A0</div><blockquot= e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width= :1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-lef= t:1ex"> - - - - - - - - - - - -<br> <br> =C2=A0 =C2=A0 {1} =C2=A0 =C2=A0 =C2=A0 =C2=A0 // one-element tuple<br> <br> I presume this too will be accepted as 1-tuple:<br> <br> =C2=A0 =C2=A0 {1,}<br></blockquote><div><br></div><div style>Currently D al= lows redundant commas in some places.</div><div style>void foo(int x, int y= ,) {}</div><div style>enum E { a =3D 1, b =3D 2, }</div><div style>auto arr= =3D [1,2,3,];<br> </div><div style><br></div><div style>So, compiler would accept following t= uples.</div><div style><br></div><div style>auto tup =3D {1,};</div><div st= yle>auto tup =3D {1,&quot;hi&quot;,};<br></div><div style>=C2=A0<br></div><= blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-l= eft-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;pa= dding-left:1ex"> - - - - - - - - - - - -<br> <br> {c, $} =3D tup; =C2=A0 // Rewritten as: c =3D tup[0];<br> <br> $ is used for array lengths, so it&#39;s not so good to overload it to mean= &quot;don&#39;t care&quot; too.<br> <br>Alternative syntaxes:<br> <br> {c, $_} =3D tup;<br> {c, } =3D tup;<br> {c, _} =3D tup;<br> {c, $$} =3D tup;<br> {c, {}} =3D tup;<br> {c, {_}} =3D tup;<br> {c, $~} =3D tup;<br> {c, ~=3D tup;<br> etc.<br></blockquote><div><br></div><div style>Placeholder token is debatab= le.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin= :0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204)= ;border-left-style:solid;padding-left:1ex"> - - - - - - - - - - - -<div class=3D"im"><br> <br> if (auto {1, y} =3D tup) {<br> =C2=A0 =C2=A0 // If the first element of tup (tup[0]) is equal to 1,<br> =C2=A0 =C2=A0 // y captures the second element of tup (tup[1]).<br> }<br> <br> <br></div> I suggest to leave that pattern matching plus conditional to a future refin= ement of tuple implementation (a second stage. And remove it from this firs= t stage proposal. So I suggest to split your proposal in two successive pro= posals). It seems handy, but D programmers need some time to go there.<br> </blockquote><div><br></div><div style>For complex tuple unpacking requires= the part of pattern matching.</div><div style><br></div><div style>auto tu= p =3D {1, {2,3,4,5,6}}<br></div><div><div>auto {x, {$, y, ...}} =3D tup; = =C2=A0 // makes nested tuple pattern for unpacking</div> <div>assert(x =3D=3D 1);</div><div>assert(y =3D=3D 3);</div><div><br></div>= </div><div style>So I&#39;d like to keep one DIP.</div><div>=C2=A0</div><bl= ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef= t-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padd= ing-left:1ex"> - - - - - - - - - - - -<br> <br> switch (tup) {<br> =C2=A0 =C2=A0 case {1, 2}:<br> =C2=A0 =C2=A0 case {$, 2}:<br> =C2=A0 =C2=A0 case {1, x}: =C2=A0 =C2=A0// capture tup[1] into &#39;x&#39; = when tup[0] =3D=3D 1<br> =C2=A0 =C2=A0 default: =C2=A0 =C2=A0 =C2=A0 =C2=A0// same as {...}<br> }<br> <br> <br> What&#39;s quite important here is the &quot;final switch&quot;. D has to m= ake sure you are considering all possible cases.<br> <br> - - - - - - - - - - - -<br> <br> I suggest to leave this to the second stage, and remove it from this propos= al:<br> <br> auto tup =3D {1, &quot;hi&quot;, 3.14, [1,2,3]};<br> if (auto {1, &quot;hi&quot;, ...} =3D tup) {}<br> <br> - - - - - - - - - - - -<br> <br> &quot;will&quot; is written badly:<div class=3D"im"><br> <br> // If the first element of coord is equal to 1 (=3D=3D x), &#39;then&#39; s= tatement wil be evaluated.<br></div></blockquote><div><br></div><div style>= Will fix.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"= margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,20= 4,204);border-left-style:solid;padding-left:1ex"> <div class=3D"im"></div> - - - - - - - - - - - -<br> <br> I think this is the third thing to leave to the second stage:<div class=3D"= im"><br>int x =3D 1;<br> if (auto {$x, y} =3D coord) { ... }<br> <br></div> - - - - - - - - - - - -<br> <br> This is nice:<br> <br> if (auto {x, y} =3D coord[]) {} =C2=A0 // same, explicitly expands fields<b= r> <br> - - - - - - - - - - - -<br> <br> This is handy and it&#39;s vaguely present in Python3, but I suggest to lea= ve this (4th thing) to the second stage:<br> <br> if (auto {num, msg, ...} =3D tup) {} =C2=A0 =C2=A0 =C2=A0// ok, `...` match= es to zero-elements.<br></blockquote><div><br></div><div style>Kenji Hara= =C2=A0</div></div></div></div> --047d7b86db60a0167804d911b042--
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 For tuple values with named fields, we need more thoughts about 
 semantics.

 alias MyPair = typeof({1, "hi"});
 alias MyRecord = typeof({count:1, msg:"hi"});
 static assert(is(MyPair == MyRecord));  // true or false?
 static assert(is(MyPair  : MyRecord));  // true or false?
 static assert(is(MyRecord  : MyPair));  // true or false?
 alias MyStudent = typeof({num:1, name:"John"});
 static assert(is(MyRecord == MyStudent));  // true or false?

One solution: http://en.wikipedia.org/wiki/Covariance_and_contravariance_%28computer_science%29 {count:1, "hi"} and {1, msg:"hi"} are invariant. {count:1, msg:"hi"}, {count:1, "hi"} and {1, msg:"hi"} are covariant to {1, "hi"}. But I think it's better to leave this to the Stage2. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--f46d04462e66ffc03f04d911fa1c
Content-Type: text/plain; charset=UTF-8

2013/3/29 Timon Gehr <timon.gehr gmx.ch>

 Looks quite nice. I especially like the {a, b} => ... thing.

 I think, however, that there are a handful serious flaws that need to be
 addressed:

 0 "Inside tuple literal, ; never appears."
   {{;}}           // a tuple not matching your specification

It will be parsed as: { // tuple braces {;} // function literal braces }
   {{if(foo()){}}} // a non-tuple matching your specification

{ // tuple braces { // function literal braces if (foo()){} // "if" always appears in statement scope } }
 1 "Note: Cannot swap values by tuple assignment."
   IMO a no-go. The syntax is too accessible to introduce this kind of
   pitfall.

Allowing value swap in tuple assignment will make language complex. I can't agree with it.
 2 "// Error: cannnot use $ inside a function literal"
   That's a DMD-ism presumably stemming from laziness during "fixing" of
   an ICE/wrong code bug or something. I'd hate to carry this over to
   the spec. Don't rely on it. The disambiguation is arbitrary, but may
   be necessary. (It's not like it is a case actually occurring in real
   code.)

 3 Unpacking / pattern matching is underspecified.
   - Do patterns nest?

I think it should be allowed.
   - Which right-hand sides are allowed with which semantics?

Whether it is a pattern or a tuple-literal, is distinguished by their appeared locations.
   - Which left-hand sides are allowed with which semantics?
     eg, what about:
       ref int foo() { ... }
       { foo(), foo() } = {1, 2};

It will be lowered to: // { foo(), foo() } = {1, 2}; foo() = 1; foo() = 2;
 4 There is no way to capture the part matched by "..."

I think this should be allowed. auto {x, r...} = tup; // Lowered to: // auto x = tup[0]; // auto r = tup[1..$] `...` is very consistent token for this purpose. template X(T...) {} alias x = X!(int, long); // T captures {int, long}
 5 .expand (or similar) property is missing.

Use tup[]. It is already exists.
 6 Relation to {a: 2, b: 3}-style struct literals not explained.

I am skeptical of the necessity of tuple literal with named fields. 7 Tuple unpacking for template parameters not mentioned.
 Is there a migration path for Phobos tuples planned?

 Eg. template Tuple(T...){ alias Tuple = {T}; }
     (field spec parsing left out for illustration)

Kenji Hara --f46d04462e66ffc03f04d911fa1c Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">2013/3/29 Timon Gehr <span dir=3D"ltr">&lt;<a href=3D"mail= to:timon.gehr gmx.ch" target=3D"_blank">timon.gehr gmx.ch</a>&gt;</span><br=
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D=

r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <div class=3D"im"><span style=3D"color:rgb(34,34,34)">Looks quite nice. I e= specially like the {a, b} =3D&gt; ... thing.</span><br></div> <br> I think, however, that there are a handful serious flaws that need to be ad= dressed:<div class=3D"im"><br>0 &quot;Inside tuple literal, ; never appears= .&quot;<br></div> =C2=A0 {{;}} =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // a tuple not matching you= r specification<br> </blockquote><div><br></div><div style>It will be parsed as:</div><div styl= e>{ =C2=A0 =C2=A0 // tuple braces</div><div style>=C2=A0 =C2=A0 {;} =C2=A0 = // function literal braces</div><div>}</div><div>=C2=A0</div><blockquote cl= ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px= ;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1e= x"> =C2=A0 {{if(foo()){}}} // a non-tuple matching your specification<br></bloc= kquote><div><br></div><div style>{ =C2=A0 =C2=A0// tuple braces</div><div s= tyle>=C2=A0 =C2=A0 { =C2=A0 =C2=A0// function literal braces</div><div styl= e>=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (foo()){} =C2=A0 // &quot;if&quot; always = appears in statement scope</div> <div style>=C2=A0 =C2=A0 }</div><div>}</div><div>=C2=A0<br></div><blockquot= e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width= :1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-lef= t:1ex"> 1 &quot;Note: Cannot swap values by tuple assignment.&quot;<br> =C2=A0 IMO a no-go. The syntax is too accessible to introduce this kind of<= br> =C2=A0 pitfall.<br></blockquote><div><br></div><div style>Allowing value sw= ap in tuple assignment will make language complex. I can&#39;t agree with i= t.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:= 0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);= border-left-style:solid;padding-left:1ex"> 2 &quot;// Error: cannnot use $ inside a function literal&quot;<br> =C2=A0 That&#39;s a DMD-ism presumably stemming from laziness during &quot;= fixing&quot; of<br> =C2=A0 an ICE/wrong code bug or something. I&#39;d hate to carry this over = to<br> =C2=A0 the spec. Don&#39;t rely on it. The disambiguation is arbitrary, but= may<br> =C2=A0 be necessary. (It&#39;s not like it is a case actually occurring in = real<br> =C2=A0 code.)<br> <br> 3 Unpacking / pattern matching is underspecified.<br> =C2=A0 - Do patterns nest?<br></blockquote><div><br></div><div style>I thin= k it should be allowed.</div><div>=C2=A0</div><blockquote class=3D"gmail_qu= ote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-co= lor:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> =C2=A0 - Which right-hand sides are allowed with which semantics?<br></bloc= kquote><div><br></div><div style>Whether it is a pattern or a tuple-literal= , is distinguished by their appeared locations.</div><div>=C2=A0</div><bloc= kquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-= width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;paddin= g-left:1ex"> =C2=A0 - Which left-hand sides are allowed with which semantics?<br> =C2=A0 =C2=A0 eg, what about:<br> =C2=A0 =C2=A0 =C2=A0 ref int foo() { ... }<br> =C2=A0 =C2=A0 =C2=A0 { foo(), foo() } =3D {1, 2};<br></blockquote><div><br>= </div><div style>It will be lowered to:</div><div style>// { foo(), foo() }= =3D {1, 2};<br></div><div style>foo() =3D 1;</div><div style>foo() =3D 2;<= /div><div>=C2=A0<br></div> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> 4 There is no way to capture the part matched by &quot;...&quot;<br></block= quote><div><br></div><div style>I think this should be allowed.</div><div><= br></div><div>auto {x, r...} =3D tup;</div><div>// Lowered to:</div><div> // auto x =3D tup[0];</div><div>// auto r =3D tup[1..$]</div><div><br></div=
<div>`...` is very consistent token for this purpose.</div><div><br></div>=

ptures {int, long}</div> <div>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px = 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);bord= er-left-style:solid;padding-left:1ex"> 5 .expand (or similar) property is missing.<br></blockquote><div><br></div>= <div style>Use tup[]. It is already exists.</div><div>=C2=A0</div><blockquo= te class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-widt= h:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-le= ft:1ex"> 6 Relation to {a: 2, b: 3}-style struct literals not explained.<br></blockq= uote><div><br></div><div><div>I am skeptical of the necessity of tuple lite= ral with named fields.</div></div><div><br></div><blockquote class=3D"gmail= _quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left= -color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> 7 Tuple unpacking for template parameters not mentioned.<br> <br> <br> Is there a migration path for Phobos tuples planned?<br> <br> Eg. template Tuple(T...){ alias Tuple =3D {T}; }<br> =C2=A0 =C2=A0 (field spec parsing left out for illustration)<br> </blockquote></div><br></div><div class=3D"gmail_extra" style>Kenji Hara</d= iv></div> --f46d04462e66ffc03f04d911fa1c--
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 5 .expand (or similar) property is missing.

Use tup[]. It is already exists.

You are right, I didn't know/remember about that: import std.typecons; void foo(int, int) {} void main() { auto t = tuple(1, 2); foo(t.tupleof); foo(t[]); auto t2 = tuple(1, 2, 3); foo(t2[0 .. 2]); } But I don't like that. t2[0 .. 2] should return a new tuple that contains just the first two items. And like every one tuple it's not supposed to auto-unpack. So I think this is a design mistake that should be fixed in the new tuples. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--089e013c6c0ee60a9f04d912679e
Content-Type: text/plain; charset=UTF-8

2013/3/30 Timon Gehr <timon.gehr gmx.ch>

 On 03/29/2013 04:32 PM, kenji hara wrote:

 2013/3/29 Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>>
 It will be parsed as:
 {     // tuple braces

It contains ';', therefore the DIP says it is a function literal brace. {;} // function literal braces
 }

        {{if(foo()){}}} // a non-tuple matching your specification


 {    // tuple braces
      {    // function literal braces

There is no ';', therefore the DIP says it is a tuple brace. if (foo()){} // "if" always appears in statement scope
      }
 }


Sorry my incomplete description and poor English. I'll improve description in DIP.
 Allowing value swap in tuple assignment will make language complex. I
 can't agree with it.

Quite obviously it is the other way round. There will be a never-ending flood of d.D.learn posts on the topic.

Yes, I agree with it. But, I won't change my opinion. So I'll stop talking about that.
         - Which right-hand sides are allowed with which semantics?
 Whether it is a pattern or a tuple-literal, is distinguished by their
 appeared locations.

Obviously, but this statement is not related to my question. Valid right-hand sides seem to be at least tuples and expanded tuples (sequences). Anything else?

Sorry I don't understand you question. 4 There is no way to capture the part matched by "..."
 I think this should be allowed.

 auto {x, r...} = tup;
 // Lowered to:
 // auto x = tup[0];
 // auto r = tup[1..$]

 `...` is very consistent token for this purpose.

Questionable. template X(T...) {}
 alias x = X!(int, long);  // T captures {int, long}

5 .expand (or similar) property is missing.
 Use tup[]. It is already exists.

Slicing obviously shouldn't auto-expand. It's a shortcoming of the Phobos tuple introduced because static slicing cannot be overloaded.

I think it will become reasonable. If you really want re-packing tuple, you can use {tup[0..1]}. It's quite handy. 6 Relation to {a: 2, b: 3}-style struct literals not explained.
 I am skeptical of the necessity of tuple literal with named fields.

distinguish the two, and how. 7 Tuple unpacking for template parameters not mentioned.


Is there a migration path for Phobos tuples planned?
     Eg. template Tuple(T...){ alias Tuple = {T}; }
          (field spec parsing left out for illustration)


Kenji Hara --089e013c6c0ee60a9f04d912679e Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">2013/3/30 Timon Gehr <span dir=3D"ltr">&lt;<a href=3D"mail= to:timon.gehr gmx.ch" target=3D"_blank">timon.gehr gmx.ch</a>&gt;</span><br=
<div class=3D"gmail_extra"><div class=3D"gmail_quote"><blockquote class=3D=

r-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> On 03/29/2013 04:32 PM, kenji hara wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> 2013/3/29 Timon Gehr &lt;<a href=3D"mailto:timon.gehr gmx.ch" target=3D"_bl= ank">timon.gehr gmx.ch</a> &lt;mailto:<a href=3D"mailto:timon.gehr gmx.ch" = target=3D"_blank">timon.gehr gmx.ch</a>&gt;&gt;<div class=3D"im">It will be= parsed as:<br> </div><div class=3D"im"> { =C2=A0 =C2=A0 // tuple braces<br> </div></blockquote> <br> It contains &#39;;&#39;, therefore the DIP says it is a function literal br= ace.<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> =C2=A0 =C2=A0 =C2=A0{;} =C2=A0 // function literal braces<div class=3D"im">= <br> }<br> <br> =C2=A0 =C2=A0 =C2=A0 =C2=A0{{if(foo()){}}} // a non-tuple matching your spe= cification<br> <br> <br></div><div class=3D"im"> { =C2=A0 =C2=A0// tuple braces<br> =C2=A0 =C2=A0 =C2=A0{ =C2=A0 =C2=A0// function literal braces<br> </div></blockquote> <br> There is no &#39;;&#39;, therefore the DIP says it is a tuple brace.<div cl= ass=3D"im"><br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0if (foo()){} =C2=A0 // &quot;if&quot; alw= ays appears in statement scope<br> =C2=A0 =C2=A0 =C2=A0}<br> }<br> <br> </blockquote> <br></div> I know how it _should_ be. The DIP contradicts what you say.<br></blockquot= e><div><br></div><div style>Sorry my incomplete description and poor Englis= h. I&#39;ll improve description in DIP.</div><div>=C2=A0=C2=A0</div><blockq= uote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-wi= dth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-= left:1ex"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> Allowing value swap in tuple assignment will make language complex. I<br> can&#39;t agree with it.<br> </div></blockquote> <br> Quite obviously it is the other way round. There will be a never-ending flo= od of d.D.learn posts on the topic.<br></blockquote><div><br></div><div sty= le>Yes, I agree with it. But, I won&#39;t change my opinion. So I&#39;ll st= op talking about that.</div> <div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px = 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-l= eft-style:solid;padding-left:1ex"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 =C2=A0 =C2=A0- Which right-hand sides are allowed with which = semantics?<br> <br> <br></div><div class=3D"im"> Whether it is a pattern or a tuple-literal, is distinguished by their<br> appeared locations.<br> </div></blockquote> <br> Obviously, but this statement is not related to my question.<br> Valid right-hand sides seem to be at least tuples and expanded tuples (sequ= ences). Anything else?<br></blockquote><div><br></div><div style>Sorry I do= n&#39;t understand you question.</div><div><br></div><blockquote class=3D"g= mail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-= left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 4 There is no way to capture the part matched by &quot;...&qu= ot;<br> <br> <br></div><div class=3D"im"> I think this should be allowed.<br> <br> auto {x, r...} =3D tup;<br> // Lowered to:<br> // auto x =3D tup[0];<br> // auto r =3D tup[1..$]<br> <br> `...` is very consistent token for this purpose.<br> </div></blockquote> <br> Questionable.<div class=3D"im"><br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> template X(T...) {}<br> alias x =3D X!(int, long); =C2=A0// T captures {int, long}<br> <br> </blockquote> <br></div> Not really. T captures {int, long}.expand.<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 5 .expand (or similar) property is missing.<br> <br> <br></div><div class=3D"im"> Use tup[]. It is already exists.<br> </div></blockquote> <br> Slicing obviously shouldn&#39;t auto-expand. It&#39;s a shortcoming of the = Phobos tuple introduced because static slicing cannot be overloaded.<br></b= lockquote><div><br></div><div style>I think it will become reasonable. If y= ou really want re-packing tuple, you can use {tup[0..1]}. It&#39;s quite ha= ndy.</div> <div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0p= x 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-lef= t-style:solid;padding-left:1ex"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 6 Relation to {a: 2, b: 3}-style struct literals not explaine= d.<br> <br> <br></div><div class=3D"im"> I am skeptical of the necessity of tuple literal with named fields.<br> <br> </div></blockquote> <br> Sure, but you&#39;d at least have to argue in the DIP that the parser can d= istinguish the two, and how.<br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 7 Tuple unpacking for template parameters not mentioned.<br><= /div></blockquote></blockquote><div><br></div><div style>Will add descripti= on about it.=C2=A0</div><div style><br></div><blockquote class=3D"gmail_quo= te" style=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-col= or:rgb(204,204,204);border-left-style:solid;padding-left:1ex"> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"><div class=3D"im"> =C2=A0 =C2=A0 Is there a migration path for Phobos tuples planned?<br> <br> =C2=A0 =C2=A0 Eg. template Tuple(T...){ alias Tuple =3D {T}; }<br> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(field spec parsing left out for illustra= tion)<br></div></blockquote></blockquote><div><br></div><div style>I have n= o plan.</div><div style><br></div><div style>Kenji Hara=C2=A0</div></div></= div></div> --089e013c6c0ee60a9f04d912679e--
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 I think it will become reasonable. If you really want 
 re-packing tuple, you
 can use {tup[0..1]}. It's quite handy.

This is a bad idea. It is not handy and it introduces a special case. Explicit is better than implicit. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent kenji hara <k.hara.pg gmail.com> writes:
--047d7b86db605a20ba04d912eb22
Content-Type: text/plain; charset=UTF-8

2013/3/30 bearophile <bearophileHUGS lycos.com>

 kenji hara:


  I think it will become reasonable. If you really want re-packing tuple,
 you
 can use {tup[0..1]}. It's quite handy.

This is a bad idea. It is not handy and it introduces a special case. Explicit is better than implicit.

That is "explicit". In D, opened tuple (currently it's generated from template parameters, e.g. std.typetuple.TypeTuple) and closed tuple (currently created by structs with alias tuple_field this; e.g. std.typecons.Tuple) are distinct. Slice operator always returns opened tuple. If tup[0..1] makes closed tuple implicitly, you cannot make new flattened tuple from other tuples. auto x = {1,"hi"}; auto y = {[1,2], S(1)}; auto tup1 = {x[], y[]}; // creates {1,"hi", [1,2], S(1)} auto tup2 = {x, y}; // creates {{1,"hi"}, {[1,2], S(1)}} Under your semantics, it is impossible. Kenji Hara. --047d7b86db605a20ba04d912eb22 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">2013/3/30 bearophile <span dir=3D"ltr">&lt;<a href=3D"mail= to:bearophileHUGS lycos.com" target=3D"_blank">bearophileHUGS lycos.com</a>= &gt;</span><br><div class=3D"gmail_extra"><div class=3D"gmail_quote"><block= quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w= idth:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding= -left:1ex"> kenji hara:<div class=3D"im"><br> <br> <blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-= left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;p= adding-left:1ex"> I think it will become reasonable. If you really want re-packing tuple, you= <br> can use {tup[0..1]}. It&#39;s quite handy.<br> </blockquote> <br></div> This is a bad idea. It is not handy and it introduces a special case. Expli= cit is better than implicit.<br></blockquote><div><br></div><div style>That= is &quot;explicit&quot;. In D, opened tuple (currently it&#39;s generated = from template parameters, e.g. std.typetuple.TypeTuple) and closed tuple (c= urrently created by structs with alias tuple_field this; e.g. std.typecons.= Tuple) are distinct. Slice operator always returns opened tuple.</div> <div style>If tup[0..1] makes closed tuple implicitly, you cannot make new = flattened tuple from other tuples.</div><div style><br></div><div style>aut= o x =3D {1,&quot;hi&quot;};</div><div style>auto y =3D {[1,2], S(1)};</div> <div style>auto tup1 =3D {x[], y[]}; =C2=A0 // creates {1,&quot;hi&quot;, [= 1,2], S(1)}</div><div style>auto tup2 =3D {x, y}; =C2=A0 // creates {{1,&qu= ot;hi&quot;}, {[1,2], S(1)}}<br></div><div style><br></div><div style>Under= your semantics, it is impossible.</div> <div style><br></div><div style>Kenji Hara.</div><div style><br></div></div=
</div></div>

--047d7b86db605a20ba04d912eb22--
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 If tup[0..1] makes closed tuple implicitly, you cannot make new 
 flattened
 tuple from other tuples.

 auto x = {1,"hi"};
 auto y = {[1,2], S(1)};
 auto tup1 = {x[], y[]};   // creates {1,"hi", [1,2], S(1)}
 auto tup2 = {x, y};   // creates {{1,"hi"}, {[1,2], S(1)}}

 Under your semantics, it is impossible.

I (and probably Timon) am just asking for another syntax to do that. Not to make it impossible. A clean syntax to concatenate tuples: auto tup3 = x ~ y; // creates {1,"hi", [1,2], S(1)} In general I agree we need a syntax to apply the tuple items to a function. But I think the slice syntax is the wrong syntax for it. In Python you use a star, this syntax can't be used in D:
 def foo(x, y): pass



 t = (1, 2)
 foo(*t)



In the Python itertools there is also a map that performs a star too:
 from itertools import starmap
 pow(2, 3)



 t = (2, 3)
 list(starmap(pow, [t]))



In Haskell there is more than one way to do that, like using uncurry that creates a new function: Prelude> mod 10 4 2 Prelude> let t = (10, 4) Prelude> let mod2 = uncurry mod Prelude> mod2 t 2 Prelude> uncurry mod (10, 4) 2 Bye, bearophile
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 I think it will become reasonable. If you really want 
 re-packing tuple, you
 can use {tup[0..1]}. It's quite handy.

In the end it's not too much bad (despite my first instinct is for a slice of a tuple to be a true tuple), and so far I have not found better alternatives. Let's see what other people think about that. Bye, bearophile
Mar 29 2013
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 03/29/2013 09:57 AM, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

One quite ugly thing about this is that function arguments will be a distinct, incompatible and underpowered form of packing together and unpacking multiple values. auto foo(int a, int b){ } // unpacking void main(){ foo(1,2); // packing } Ideal for UFCS would be: {a,b}.zip.map!({x,y}=>x+y); It is therefore likely that people will start to write two overloads, where one takes multiple arguments and the other takes one tuple argument.
Mar 29 2013
prev sibling next sibling parent "angel" <andrey.gelman gmail.com> writes:
Another reason to allow swapping values ( {a, b} = {b, a} ) is 
nice parallel semantics that might provide cool features on some 
future (or niche) parallel hardware.
Think of
{a, b} = {funcA(), funcB()};
Parallel semantics is able to evolve to parallel execution, which 
is one cool feature.
In Go language it is so.
Mar 29 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
kenji hara:

 http://wiki.dlang.org/DIP32

Regarding case values:
 switch (tup) {
     case {1, 2}:
     case {$, 2}:
     case {1, x}:    // capture tup[1] into 'x' when tup[0] == 1
     default:        // same as {...}
 }

It's useful to switch on struct values: import std.bigint; void main() { auto x = BigInt(3); switch (x) { case BigInt(0): break; default: break; } } Other examples of Phobos structs that is useful to switch on are Nullable, Algebraic, etc. Switching on structs is more easy if the struct has no ctor. So it's a POD (despite having some other method). To support the general case of structs that have a constructor such structs need a standard method named like "unapply", that is used by the switch itself. This is the solution used by Scala language: http://www.scala-lang.org/node/112 This example is in Scala language: object Twice { def apply(x: Int): Int = x * 2 def unapply(z: Int): Option[Int] = if (z%2 == 0) Some(z/2) else None } object TwiceTest extends Application { val x = Twice(21) x match { case Twice(n) => Console.println(n) } // prints 21 } It's equivalent to the D code: import std.stdio; import std.typecons: Nullable; struct Twice { int static opCall(int x) { return x * 2; } Nullable!int unapply(int z) { if (z % 2 == 0) return typeof(return)(z / 2); else return typeof(return).init; } } void main() { immutable int x = Twice(21); assert(x == 42); switch (x) { case Twice(n): writeln(n); // prints 21 break; default: } } A different example: import std.stdio; import std.typecons: Nullable; struct Foo { int x; this(int x_) { this.x = x_ * 2; } Nullable!int unapply(Foo f1) const { return typeof(return)(f1.x / 2); } } void main() { immutable Foo f2 = Foo(10); assert(f1.x == 20); switch (f2) { case Foo(5): writeln("First case: 5"); break; case Foo(n): writeln(n); // Prints: 10 break; default: } } A third example: import std.stdio; struct Even { bool unapply(int x) { return x % 2 == 0; } } void main() { int x = 17; switch (x) { case Even(): writeln("even"); break; default: writeln("odd"); } } unapply() is allowed to return a bool or a Nullable (including a Nullable of a tuple). For more info: http://lamp.epfl.ch/~emir/written/MatchingObjectsWithPatterns-TR.pdf Bye, bearophile
Mar 29 2013
prev sibling next sibling parent Timothee Cour <thelastmammoth gmail.com> writes:
not 'open', there is already something called .expand property

http://forum.dlang.org/thread/fdkalkzhchuerkqlpzkg forum.dlang.org

how about this:
auto x = {1,2,3};
auto x2 = {1,2};
assert(x[0..2]==x2);//no expansion
void fun(int x, int y);
fun(x2.expand);
fun(x[0..2].expand);

keeps slicing orthogonal from expansion

 On Fri, Mar 29, 2013 at 10:31 AM, Timon Gehr <timon.gehr gmx.ch> wrote:
 On 03/29/2013 05:39 PM, kenji hara wrote:
 2013/3/30 bearophile <bearophileHUGS lycos.com
 <mailto:bearophileHUGS lycos.com>>


     kenji hara:


         I think it will become reasonable. If you really want re-packing
         tuple, you
         can use {tup[0..1]}. It's quite handy.


     This is a bad idea. It is not handy and it introduces a special
     case. Explicit is better than implicit.


 That is "explicit".  In D, opened tuple (currently it's generated from
 template parameters, e.g. std.typetuple.TypeTuple) and closed tuple
 (currently created by structs with alias tuple_field this; e.g.
 std.typecons.Tuple) are distinct. Slice operator always returns opened
 tuple.

Because of prior language limitations, not because it makes any sense! Current operator overloading limitations mandate that it is simply not possible to create a Phobos tuple with a sane slice operator.
 If tup[0..1] makes closed tuple implicitly, you cannot make new
 flattened tuple from other tuples.

 auto x = {1,"hi"};
 auto y = {[1,2], S(1)};
 auto tup1 = {x[], y[]};   // creates {1,"hi", [1,2], S(1)}
 auto tup2 = {x, y};   // creates {{1,"hi"}, {[1,2], S(1)}}

 Under your semantics, it is impossible.
 ...

Certainly not. Creating opened tuples from closed ones is not an operation necessarily tied to slicing. Making an opened tuple should be an explicit operation on closed tuples. Slicing and opening are orthogonal operations. auto tup1 = {x.open, y.open}; // creates {1,"hi", [1,2], S(1)} auto tup2 = {x[0..2], y[]}; // creates {{1,"hi}, {[1,2], S(1)}} auto tup3 = {x[0..2].open, y[].open}; // creates {1,"hi", [1,2], S(1)}


Mar 30 2013
prev sibling next sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Friday, 29 March 2013 at 12:56:10 UTC, bearophile wrote:
 $ 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.

{c, ?} = tup;
Mar 30 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Zach the Mystic:

 {c, $_} = tup;
 {c,  } = tup;
 {c,  _} = tup;
 {c, $$} = tup;
 {c, {}} = tup;
 {c, {_}} = tup;
 {c, $~} = tup;
 {c,  ~= tup;
 etc.

{c, ?} = tup;

Right, I was forgetting that. Or this if you want to keep the single "?" for hypothetical future nullable types: {c, ?_} = tup; Bye, bearophile
Mar 30 2013
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
On Friday, 29 March 2013 at 15:47:52 UTC, Timon Gehr wrote:
 template X(T...) {}
 alias x = X!(int, long);  // T captures {int, long}

Not really. T captures {int, long}.expand.

Should there be a difference?
Mar 31 2013
prev sibling next sibling parent "Traveler" <nooneknows example.com> writes:
On Friday, 29 March 2013 at 08:58:06 UTC, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

Why not square brackets? int i; string str; [i, str] = [5, "line"]; Tuple as alias to Object[] or to Variant[].
Apr 01 2013
prev sibling next sibling parent =?utf-8?Q?Simen_Kj=C3=A6r=C3=A5s?= <simen.kjaras gmail.com> writes:
On Mon, 01 Apr 2013 09:08:47 +0200, Traveler <nooneknows example.com>  
wrote:

 On Friday, 29 March 2013 at 08:58:06 UTC, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

Why not square brackets? int i; string str; [i, str] = [5, "line"]; Tuple as alias to Object[] or to Variant[].

Mostly because it already has a meaning in D, namely that of an array. What you have above certainly does not compile, but consider the case of a homogeneous tuple: int i = 1, j = 2; [i, j] = [3, 4]; This is equivalent to this code: [1, 2] = [3, 4]; Which of course is nonsense, but it already has a meaning. Using an existing syntax leads to many many more corner cases and gray areas than creating a new syntax does. Of course, {} also has a meaning already, but the overlap of semantics is much smaller, and thus the potential corner cases and gray areas are fewer and smaller. -- Simen
Apr 01 2013
prev sibling next sibling parent "Kagamin" <spam here.lot> writes:
By the way, {int,int} - is it a type or a value?

auto t={int,int};
t[1] a;
^what is this? 1-element array of {int,int} tuples or `int a;` ?
Apr 01 2013
prev sibling next sibling parent reply "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
Two different languages I've used in the distant past used   for 
expansion.

auto t1 = {1, "hi"};
auto t2 = {2, "yo"};

auto t3 = {t1, t2}; // == {{1, "hi"}, {2, "yo"}}
auto t4 = { t1,  t2}; // == {1, "hi", 2, "yo"}

Are there still unspecified plans for  , or is it now available 
for something like this?

Regarding the $ident syntax (which I was glad to see, since my 
first question when reading the DIP was whether a way existed to 
do that), couldn't the   syntax then be allowed for this as well, 
with expansion of a scalar defined as the scalar itself?

int x = 1;
if ( auto { x, y} = tmp ) // {1, y} = tmp

if ( auto {x, y} = tmp } // same as in DIP
Apr 01 2013
parent Jacob Carlborg <doob me.com> writes:
On 2013-04-02 02:16, Chris Nicholson-Sauls wrote:
 Two different languages I've used in the distant past used   for expansion.

 auto t1 = {1, "hi"};
 auto t2 = {2, "yo"};

 auto t3 = {t1, t2}; // == {{1, "hi"}, {2, "yo"}}
 auto t4 = { t1,  t2}; // == {1, "hi", 2, "yo"}

 Are there still unspecified plans for  , or is it now available for
 something like this?

 Regarding the $ident syntax (which I was glad to see, since my first
 question when reading the DIP was whether a way existed to do that),
 couldn't the   syntax then be allowed for this as well, with expansion
 of a scalar defined as the scalar itself?

 int x = 1;
 if ( auto { x, y} = tmp ) // {1, y} = tmp

 if ( auto {x, y} = tmp } // same as in DIP

Won't there be a conflict with UDA's? -- /Jacob Carlborg
Apr 01 2013
prev sibling next sibling parent "Chris Nicholson-Sauls" <ibisbasenji gmail.com> writes:
On Tuesday, 2 April 2013 at 06:42:00 UTC, Jacob Carlborg wrote:
 On 2013-04-02 02:16, Chris Nicholson-Sauls wrote:
 Two different languages I've used in the distant past used   
 for expansion.

 auto t1 = {1, "hi"};
 auto t2 = {2, "yo"};

 auto t3 = {t1, t2}; // == {{1, "hi"}, {2, "yo"}}
 auto t4 = { t1,  t2}; // == {1, "hi", 2, "yo"}

 Are there still unspecified plans for  , or is it now 
 available for
 something like this?

 Regarding the $ident syntax (which I was glad to see, since my 
 first
 question when reading the DIP was whether a way existed to do 
 that),
 couldn't the   syntax then be allowed for this as well, with 
 expansion
 of a scalar defined as the scalar itself?

 int x = 1;
 if ( auto { x, y} = tmp ) // {1, y} = tmp

 if ( auto {x, y} = tmp } // same as in DIP

Won't there be a conflict with UDA's?

Oh yeah, those exist. (I seriously forgot... just because I haven't gotten to play with recent D releases any.)
Apr 02 2013
prev sibling next sibling parent "timotheecour" <timothee.cour2 gmail.com> writes:
On Saturday, 30 March 2013 at 18:05:27 UTC, bearophile wrote:
 Zach the Mystic:

 {c, $_} = tup;
 {c,  } = tup;
 {c,  _} = tup;
 {c, $$} = tup;
 {c, {}} = tup;
 {c, {_}} = tup;
 {c, $~} = tup;
 {c,  ~= tup;
 etc.

{c, ?} = tup;

Right, I was forgetting that. Or this if you want to keep the single "?" for hypothetical future nullable types: {c, ?_} = tup;

What about ---- {c, void} = tup; ---- (proposed by Hara Kenji in the original AutoTupleDeclaration declaration pull request https://github.com/D-Programming-Language/dmd/pull/341 ) (and, independently of the missing symbol choice) ---- {a,b,void...} = tup; //tup = {1,2,3,4,5}; ----
Apr 05 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
timotheecour:

 What about
 ----
 {c, void} = tup;

I think the question mark is better here. It's shorter and it has only one meaning. Bye, bearophile
Apr 05 2013
prev sibling next sibling parent "Zach the Mystic" <reachzach gggggmail.com> writes:
On Friday, 5 April 2013 at 23:49:49 UTC, bearophile wrote:
 timotheecour:

 What about
 ----
 {c, void} = tup;

I think the question mark is better here. It's shorter and it has only one meaning. Bye, bearophile

Not disagreeing, but you had mentioned nullable types before, and I was wondering what they might look like also. Have you made an enhancement for these I could examine?
Apr 05 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Zach the Mystic:

 Not disagreeing, but you had mentioned nullable types before, 
 and I was wondering what they might look like also. Have you 
 made an enhancement for these I could examine?

I opened this: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Part of the syntax is: T? means T nullable T = means not nullable. But that ER is a confused mess, and in the meantime the disable was introduced. Now the probability of such nullable syntax+semantics to be introduced in D is very low, so probably I will close down that ER. Bye, bearophile
Apr 06 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrei Alexandrescu:

 I think it's safe to close it. Nullable types have not enjoyed 
 a lot of appreciation in C#.

On the other hand they have gained appreciation in almost every one of the other recent languages, as F#, Scala, Rust, and few Java-Like languages running on the JavaVM, so this is a not small failure point of D. I think all type-rich languages that will be designed in future will have nonnullable typing. D is old-school on this. Bye, bearophile
Apr 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 6 April 2013 at 12:41:46 UTC, Andrei Alexandrescu 
wrote:
 On 4/6/13 4:10 AM, bearophile wrote:
 Zach the Mystic:

 Not disagreeing, but you had mentioned nullable types before, 
 and I
 was wondering what they might look like also. Have you made an
 enhancement for these I could examine?

I opened this: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Part of the syntax is: T? means T nullable T = means not nullable. But that ER is a confused mess, and in the meantime the disable was introduced. Now the probability of such nullable syntax+semantics to be introduced in D is very low, so probably I will close down that ER. Bye, bearophile

I think it's safe to close it. Nullable types have not enjoyed a lot of appreciation in C#. Andrei

In C#, all objects are already nullables, which make it not really useful. In D, this is implementable as a lib anyway.
Apr 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 29 March 2013 at 08:58:06 UTC, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

The {} syntax is already crowded, I don't think this is wise to use it here. Timon already presented plenty of cases where it isn't as simple as presented in the DIP, and I can come up with a bunch of my own to add here. It don't think this is necessary as point have been made. As a side note, I'd vote for deprecation of the {} syntax for structs to merge it with whatever is decided for tuples.
Apr 06 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Saturday, 6 April 2013 at 12:59:53 UTC, bearophile wrote:
 Andrei Alexandrescu:

 I think it's safe to close it. Nullable types have not enjoyed 
 a lot of appreciation in C#.

On the other hand they have gained appreciation in almost every one of the other recent languages, as F#, Scala, Rust, and few Java-Like languages running on the JavaVM, so this is a not small failure point of D. I think all type-rich languages that will be designed in future will have nonnullable typing. D is old-school on this.

Non nullable should be the default. Compiler know know how to track initialization.
Apr 06 2013
prev sibling next sibling parent "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Saturday, 6 April 2013 at 08:10:30 UTC, bearophile wrote:
 Zach the Mystic:

 Not disagreeing, but you had mentioned nullable types before, 
 and I was wondering what they might look like also. Have you 
 made an enhancement for these I could examine?

I opened this: http://d.puremagic.com/issues/show_bug.cgi?id=4571 Part of the syntax is: T? means T nullable T = means not nullable. But that ER is a confused mess, and in the meantime the disable was introduced. Now the probability of such nullable syntax+semantics to be introduced in D is very low, so probably I will close down that ER. Bye, bearophile

Once dmd pull 1724 is merged, it would be possible to write: class A {} enum E : A { e = new A } void main() { E e; //a is allocated on heap } So, E type is some kind of nullable type (but this approach has drawbacks).
Apr 06 2013
prev sibling next sibling parent "Philip Stuckey" <pstuc002.public gmail.com> writes:
On Friday, 29 March 2013 at 08:58:06 UTC, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

I'm not sure if this is off topic or redundant but couldn't many of these things be added to the standard library without a special syntax. for instance s function like unpack could allow import std.typecons; int a; char b ; unpack(a,b) = tuple(5, 'A'); assert(a==5 && b=='A'); instead 0f (int a, char b) = (5,'A'); or whatever. Would this help the problem?
Aug 13 2014
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 13 August 2014 at 23:02:44 UTC, Philip Stuckey 
wrote:
 I'm not sure if this is off topic or redundant but couldn't 
 many of these things be added to the standard library without a 
 special syntax. for instance s function like unpack could allow

     import std.typecons;
     int a;
     char b ;
     unpack(a,b) = tuple(5, 'A');
     assert(a==5 && b=='A');

 instead 0f

     (int a, char b) = (5,'A');

 or whatever.

 Would this help the problem?

This is already possible with standard library but the fact that declarations need to be separate makes people not happy.
Aug 13 2014
prev sibling next sibling parent "Yota" <yotaxp thatGoogleMailThing.com> writes:
On Wednesday, 13 August 2014 at 23:26:29 UTC, Dicebot wrote:
 On Wednesday, 13 August 2014 at 23:02:44 UTC, Philip Stuckey 
 wrote:
 I'm not sure if this is off topic or redundant but couldn't 
 many of these things be added to the standard library without 
 a special syntax. for instance s function like unpack could 
 allow

    import std.typecons;
    int a;
    char b ;
    unpack(a,b) = tuple(5, 'A');
    assert(a==5 && b=='A');

 instead 0f

    (int a, char b) = (5,'A');

 or whatever.

 Would this help the problem?

This is already possible with standard library but the fact that declarations need to be separate makes people not happy.

Brings to mind C#'s new ability to declare locals within 'out' arguments. if (int.TryParse("123", out int i)) { ...use 'i'... }
Aug 14 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Dicebot:

 This is already possible with standard library but the fact 
 that declarations need to be separate makes people not happy.

The unpack() lacks most of the capabilities you expect and want from tuples handling. Bye, bearophile
Aug 14 2014
prev sibling next sibling parent reply "Sean Kelly" <sean invisibleduck.org> writes:
This looks really nice.  I'd love to use it for std.concurrency,
but I'm still trying to sort out a way for this to work.
Specifically, it would be nice if there were a way to know from a
tuple's TypeInfo if it matches a pattern.  For example, would
something like this work:

receive( ({1, $} x) { ... do something with tuple x },
               ({2, $} x) ... );

I suppose it might be possible to say whether a tuple is {int,
stuff}, then deserialize it into a variable and compare against
the pattern explicitly?  Though maybe this would end up requiring
me to parse the mangled name of the tuple type?
Aug 14 2014
parent Jacob Carlborg <doob me.com> writes:
On 14/08/14 21:12, bearophile wrote:

 Elsewhere I have suggested to add to D an optional struct (and tuple)
 method now named onMatch, similar to the unapply method of Scala
 language, that is also called by the switch case to perform a basic
 version of pattern matching.

It can be implemented as a library function. The syntax won't be as nice looking tough. With AST macros the syntax could probably look good enough. -- /Jacob Carlborg
Aug 14 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Sean Kelly:

 This looks really nice.  I'd love to use it for std.concurrency,
 but I'm still trying to sort out a way for this to work.
 Specifically, it would be nice if there were a way to know from 
 a tuple's TypeInfo if it matches a pattern.

Elsewhere I have suggested to add to D an optional struct (and tuple) method now named onMatch, similar to the unapply method of Scala language, that is also called by the switch case to perform a basic version of pattern matching. Bye, bearophile
Aug 14 2014
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jacob Carlborg:

 It can be implemented as a library function.

It can't be implemented with a library function. You want to use it in function signatures, foreach, and so on. We have discussed this many times. Bye, bearophile
Aug 15 2014
prev sibling parent "Frustrated" <Who where.com> writes:
On Friday, 29 March 2013 at 08:58:06 UTC, kenji hara wrote:
 http://wiki.dlang.org/DIP32

 Kenji Hara

Will it allow for nested tuples? Or tuples containing lambdas?
Aug 15 2014