www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - A different tuple syntax

reply "bearophile" <bearophileHUGS lycos.com> writes:
Regarding the syntax to unpack tuples into single variables, 
Kenji Hara wrote a DIP (http://wiki.dlang.org/DIP32 ) denoting 
tuples with the univesal syntax {...}, but people have found some 
problems in it.

(I think Kenji didn't update that DIP with all the small 
improvements we suggested in that thread, so they risk getting 
lost.)

Maybe one solution is to use a "tup(...)" syntax, it's a bit 
heavy, but it's clear and maybe it has no corner cases:

tup(int, string) tup = tup(1, "hi");
foreach (Float; tup(float, double, real)) { ... }
auto tup(x, y) = tup(1, "hi");
tup(auto x, y) = tup(1, "hi");
tup(int x, string y) = tup(1, "hi");
foreach (i, const tup(x, y); [tup(1,2), tup(3,4), tup(5,6), ...]) 
{
void foo(tup(int, string name), string msg);
(tup(A a, B b)) => a + b;
switch (tup) { case tup(1, 2): ... }


This is not very elegant, "tup" becomes a new keyword and 
generally I don't like such strong abbreviations, like the ones 
used in Rust language, but "tuple()" clashes with the 
library-defined ones, and it's even more wordy if you want to 
define an array of them:

[tuple(1,2), tuple(3,4), tuple(5,6), ...]

Bye,
bearophile
May 30 2013
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
If you don't like to introduce a new keyword, then a different 
alternative is to use the   again, a bit like UDAs:

 {...}

 [10]  {int, string} tup =  {1, "hi"}; // With UDA.
foreach (Float;  {float, double, real}) { ... }
auto  {x, y} =  {1, "hi"};
 {auto x, y} =  {1, "hi"};
 {int x, string y} =  {1, "hi"};
foreach (i, const  {x, y}; [ {1,2},  {3,4},  {5,6}, ...]) {
void foo( {int, string name}, string msg);
( {A a, B b}) => a + b;
switch (tup) { case  {1, 2}: ... }

Bye,
bearophile
May 30 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 30.05.2013 15:02, schrieb bearophile:
 Frank Fuente:

 My eyes, they burn...

It looks a bit like Perl, it's not very nice, but for me it's not easy to find something significantly better. The syntax with tup() is longer but less noisy. Bye, bearophile

what about !(float, double, real) because the tupple syntax is near to template parameters
May 30 2013
parent reply dennis luehring <dl.soluz gmx.net> writes:
Am 30.05.2013 15:43, schrieb dennis luehring:
 Am 30.05.2013 15:02, schrieb bearophile:
 Frank Fuente:

 My eyes, they burn...

It looks a bit like Perl, it's not very nice, but for me it's not easy to find something significantly better. The syntax with tup() is longer but less noisy. Bye, bearophile

what about !(float, double, real) because the tupple syntax is near to template parameters

sadly not context free and indentical strange like !{float, double, real}
May 30 2013
parent dennis luehring <dl.soluz gmx.net> writes:
Am 30.05.2013 16:26, schrieb watcher:
 On Thursday, 30 May 2013 at 14:06:15 UTC, Diggory wrote:
 Could also do something in the style of token strings, ie.

 t{ ... }

 It's lighter than "tup" and there's a precedent for it already
 in the language with q{ ... } which also means there should be
 no issues parsing it.

These are the hacks that bring languages into a kind of brainfuck syntax. Why not keep a language easy readable and understandable. A precedence does not imply that it is a desirable thing to have.

then is the only solution to free tuple/or use tup with {} this way a tuple is similar from a syntax perspective like class or struct - the {} scope defines the interface of the tuple which are by default unnamed ordered aliases for type/value class { int a; int b; ... } tuple { int, double, "hello" } its easy to parse, context free and doesn't need a new type of scope
May 30 2013
prev sibling next sibling parent "Frank Fuente" <a b.com> writes:
On Thursday, 30 May 2013 at 12:32:46 UTC, bearophile wrote:
 If you don't like to introduce a new keyword, then a different 
 alternative is to use the   again, a bit like UDAs:

  {...}

  [10]  {int, string} tup =  {1, "hi"}; // With UDA.
 foreach (Float;  {float, double, real}) { ... }
 auto  {x, y} =  {1, "hi"};
  {auto x, y} =  {1, "hi"};
  {int x, string y} =  {1, "hi"};
 foreach (i, const  {x, y}; [ {1,2},  {3,4},  {5,6}, ...]) {
 void foo( {int, string name}, string msg);
 ( {A a, B b}) => a + b;
 switch (tup) { case  {1, 2}: ... }

 Bye,
 bearophile

My eyes, they burn...
May 30 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Frank Fuente:

 My eyes, they burn...

It looks a bit like Perl, it's not very nice, but for me it's not easy to find something significantly better. The syntax with tup() is longer but less noisy. Bye, bearophile
May 30 2013
prev sibling next sibling parent "eles" <eles eles.com> writes:
On Thursday, 30 May 2013 at 13:02:24 UTC, bearophile wrote:
 Frank Fuente:
 The syntax with tup() is longer but less noisy.

I prefer tup() over the {} thing, although I would like to have something that looks like "a syntax" instead of "a function".
May 30 2013
prev sibling next sibling parent "Diggory" <diggsey googlemail.com> writes:
Could also do something in the style of token strings, ie.

t{ ... }

It's lighter than "tup" and there's a precedent for it already in 
the language with q{ ... } which also means there should be no 
issues parsing it.
May 30 2013
prev sibling next sibling parent "watcher" <watcher watcher.org> writes:
On Thursday, 30 May 2013 at 14:06:15 UTC, Diggory wrote:
 Could also do something in the style of token strings, ie.

 t{ ... }

 It's lighter than "tup" and there's a precedent for it already 
 in the language with q{ ... } which also means there should be 
 no issues parsing it.

These are the hacks that bring languages into a kind of brainfuck syntax. Why not keep a language easy readable and understandable. A precedence does not imply that it is a desirable thing to have.
May 30 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Diggory:

 Could also do something in the style of token strings, ie.

 t{ ... }

It's less noisy than {} or ${}: auto t = t{}; // empty. [10] t{int, string} tup = t{1, "hi"}; // With UDA. foreach (Float; t{float, double, real}) { ... } auto t{x, y} = t{1, "hi"}; t{auto x, y} = t{1, "hi"}; t{int x, string y} = t{1, "hi"}; foreach (i, const t{x, y}; [t{1,2}, t{3,4}, t{5,6}, ...]) { void foo(t{int, string name}, string msg); (t{A a, B b}) => a + b; switch (tup) { case t{1, 2}: ... } Bye, bearophile
May 30 2013
prev sibling next sibling parent "Diggory" <diggsey googlemail.com> writes:
On Thursday, 30 May 2013 at 14:26:11 UTC, watcher wrote:
 On Thursday, 30 May 2013 at 14:06:15 UTC, Diggory wrote:
 Could also do something in the style of token strings, ie.

 t{ ... }

 It's lighter than "tup" and there's a precedent for it already 
 in the language with q{ ... } which also means there should be 
 no issues parsing it.

These are the hacks that bring languages into a kind of brainfuck syntax. Why not keep a language easy readable and understandable. A precedence does not imply that it is a desirable thing to have.

I'm sorry that you don't like it, but I don't see why it's any more of a hack than any of the other methods presented thus far? I've always found token strings to be exceedingly readable myself, and when new syntax is needed it's usually best to base it on some existing syntax so that there's some sort of consistency.
May 30 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Diggory:

 I'm sorry that you don't like it, but I don't see why it's any 
 more of a hack than any of the other methods presented thus far?

t{} doesn't look wonderful compared to Python-like tuples, but maybe it's the best syntax seen so far that doesn't clashes with tuple(), Tuple!(), TypeTuple!(), comma operator syntax, lambdas, parameter-less lambdas, and so on. Bye, bearophile
May 30 2013
prev sibling next sibling parent "watcher" <watcher watcher.org> writes:
On Thursday, 30 May 2013 at 16:25:27 UTC, Diggory wrote:
 On Thursday, 30 May 2013 at 14:26:11 UTC, watcher wrote:
 On Thursday, 30 May 2013 at 14:06:15 UTC, Diggory wrote:
 Could also do something in the style of token strings, ie.

 t{ ... }

 It's lighter than "tup" and there's a precedent for it 
 already in the language with q{ ... } which also means there 
 should be no issues parsing it.

These are the hacks that bring languages into a kind of brainfuck syntax. Why not keep a language easy readable and understandable. A precedence does not imply that it is a desirable thing to have.

I'm sorry that you don't like it, but I don't see why it's any more of a hack than any of the other methods presented thus far? I've always found token strings to be exceedingly readable myself, and when new syntax is needed it's usually best to base it on some existing syntax so that there's some sort of consistency.

I hope i did not sound mean. I just think that a language should not be that terse. It must be human readable with little room to make typing or other mistakes. I rather type more if necessary.
May 30 2013
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
watcher:

 I hope i did not sound mean. I just think that a language 
 should not be that terse. It must be human readable with little 
 room to make typing or other mistakes. I rather type more if 
 necessary.

I agree that too much terseness is bad, making code less easy to read. On the other hand too much long to type syntax is bad, for different reasons. So you need a compromises, between lot of tiny operators as in J, K, Ursala or Perl6 languages, that are hard to remember, understand and look in the documentation, and very long names as std.functional.binaryReverseArgs of Phobos that are too much long. Such intermediate point between too much long and too much short syntax is not a constant, it must be adapted according to how much common an operation is, in the language, across languages, or even more generally, in mathematics, and natural languages. The more common something is, the shorter it's better for it to be: http://en.wikipedia.org/wiki/Zipf%27s_law Tuples are used very often, they are not meant to be uncommon parts of the language. In range-heavy code you are probably going to use a tuple every 1-5 lines of code. And even more normal D code may use a tuple every 10-30 lines of code. So using a succinct syntax is good. Python uses just commas (with a bit of help of ( ) in some cases, like for the empty tuple), but to not break a certain compatibility with C the D language can't do the same. So we are trying to look for something that works, doesn't clash with currently used syntaxes, including library solutions like Tuple!() and tuple(), and is short enough. Tuple syntax can be short because it's going to be used often enough, and it has to be short because where you use tuples you don't want too much boilerplate, because functional-style code becomes rather worse if your syntax is not terse. That's why most functional languages, or languages with some support for functional programming (F#, Haskell, Python, Scala, and so on) have a nice short syntax for tuples. Bye, bearophile
May 30 2013
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Using   isn't pretty, but I like {} a bit since it is the
"highest-level" structuring syntax element in D which seems
right for this sort of stuff and especially when the tuple
resembles an anonymous struct.

-- 
Marco
May 30 2013
prev sibling next sibling parent "js.mdnq" <js_adddot+mdng gmail.com> writes:
On Thursday, 30 May 2013 at 12:32:46 UTC, bearophile wrote:
 If you don't like to introduce a new keyword, then a different 
 alternative is to use the   again, a bit like UDAs:

  {...}

  [10]  {int, string} tup =  {1, "hi"}; // With UDA.
 foreach (Float;  {float, double, real}) { ... }
 auto  {x, y} =  {1, "hi"};
  {auto x, y} =  {1, "hi"};
  {int x, string y} =  {1, "hi"};
 foreach (i, const  {x, y}; [ {1,2},  {3,4},  {5,6}, ...]) {
 void foo( {int, string name}, string msg);
 ( {A a, B b}) => a + b;
 switch (tup) { case  {1, 2}: ... }

 Bye,
 bearophile

Or rather # or & as they do have some inherent relation to tuples.. #(int, string) tup &(int, string) tup The second remind one it is a sort of concatenation of types. e.g., int & string.
May 30 2013
prev sibling next sibling parent "Diggory" <diggsey googlemail.com> writes:
On Thursday, 30 May 2013 at 21:40:47 UTC, js.mdnq wrote:
 On Thursday, 30 May 2013 at 12:32:46 UTC, bearophile wrote:
 If you don't like to introduce a new keyword, then a different 
 alternative is to use the   again, a bit like UDAs:

  {...}

  [10]  {int, string} tup =  {1, "hi"}; // With UDA.
 foreach (Float;  {float, double, real}) { ... }
 auto  {x, y} =  {1, "hi"};
  {auto x, y} =  {1, "hi"};
  {int x, string y} =  {1, "hi"};
 foreach (i, const  {x, y}; [ {1,2},  {3,4},  {5,6}, ...]) {
 void foo( {int, string name}, string msg);
 ( {A a, B b}) => a + b;
 switch (tup) { case  {1, 2}: ... }

 Bye,
 bearophile

Or rather # or & as they do have some inherent relation to tuples.. #(int, string) tup &(int, string) tup The second remind one it is a sort of concatenation of types. e.g., int & string.

# would not be bad, but not & as that would just be confusing...
May 30 2013
prev sibling next sibling parent Marco Leise <Marco.Leise gmx.de> writes:
Am Thu, 30 May 2013 23:48:00 +0200
schrieb "Diggory" <diggsey googlemail.com>:

 # would not be bad, but not & as that would just be confusing...

It has the additional advantage to be a non-modifier symbol on a few Latin based keyboard layouts (English, German, Maltese, ...). -- Marco
May 30 2013
prev sibling next sibling parent Peter Williams <pwil3058 bigpond.net.au> writes:
On 30/05/13 23:14, eles wrote:
 On Thursday, 30 May 2013 at 13:02:24 UTC, bearophile wrote:
 Frank Fuente:
 The syntax with tup() is longer but less noisy.

I prefer tup() over the {} thing, although I would like to have something that looks like "a syntax" instead of "a function".

Yes, don't over use {} as they'll be need for sets when they're added :-) Peter
May 30 2013
prev sibling next sibling parent "nazriel" <spam dzfl.pl> writes:
On Thursday, 30 May 2013 at 21:40:47 UTC, js.mdnq wrote:
 On Thursday, 30 May 2013 at 12:32:46 UTC, bearophile wrote:
 If you don't like to introduce a new keyword, then a different 
 alternative is to use the   again, a bit like UDAs:

  {...}

  [10]  {int, string} tup =  {1, "hi"}; // With UDA.
 foreach (Float;  {float, double, real}) { ... }
 auto  {x, y} =  {1, "hi"};
  {auto x, y} =  {1, "hi"};
  {int x, string y} =  {1, "hi"};
 foreach (i, const  {x, y}; [ {1,2},  {3,4},  {5,6}, ...]) {
 void foo( {int, string name}, string msg);
 ( {A a, B b}) => a + b;
 switch (tup) { case  {1, 2}: ... }

 Bye,
 bearophile

Or rather # or & as they do have some inherent relation to tuples.. #(int, string) tup &(int, string) tup The second remind one it is a sort of concatenation of types. e.g., int & string.

That actually looks good... I liked idea of: auto (x, y) = foo(); (int x1, string y1) = foo(); (int, string) foo() { (int tmp, string tmp2) = (3, "dsa"); return (42, "dsa"); } but it was shoot down because of various issues. Then proposal with {} risen: auto {x, y} = foo(); {int x1, string y1} = foo(); {int, string} foo() { {int tmp, string tmp2} = {3, "dsa"}; return {42, "dsa"}; } Now this: auto #(x, y) = foo(); #(int x1, string y1) = foo(); #(int, string) foo() { #(int tmp, string tmp2) = #(3, "dsa"); return #(42, "dsa"); } I like eye-candies and the 1st syntax looks the best for me but it won't happen. Both 2nd example and 3rd proposed by js.mdnq looks good but IMHO the 3rd is way more clear what is it about... also {} IMHO clash a bit with our curly-bracket based language... it gets a bit complicated where function begins, where if blocks begins and where tuple declaration begins. My 2 cents :)) bearophile what do you think?
May 30 2013
prev sibling next sibling parent Timothee Cour <thelastmammoth gmail.com> writes:
--047d7bd6b2daed753204ddfb8de3
Content-Type: text/plain; charset=ISO-8859-1

 Regarding the syntax to unpack tuples into single variables, Kenji Hara
 wrote a DIP (http://wiki.dlang.org/DIP32 ) denoting tuples with the
 univesal syntax {...}, but people have found some problems in it.

Do you have a reference to the post(s) mentioning the problems with Kenji's proposed syntax? Thanks On Thu, May 30, 2013 at 5:29 AM, bearophile <bearophileHUGS lycos.com>wrote:
 Regarding the syntax to unpack tuples into single variables, Kenji Hara
 wrote a DIP (http://wiki.dlang.org/DIP32 ) denoting tuples with the
 univesal syntax {...}, but people have found some problems in it.

 (I think Kenji didn't update that DIP with all the small improvements we
 suggested in that thread, so they risk getting lost.)

 Maybe one solution is to use a "tup(...)" syntax, it's a bit heavy, but
 it's clear and maybe it has no corner cases:

 tup(int, string) tup = tup(1, "hi");
 foreach (Float; tup(float, double, real)) { ... }
 auto tup(x, y) = tup(1, "hi");
 tup(auto x, y) = tup(1, "hi");
 tup(int x, string y) = tup(1, "hi");
 foreach (i, const tup(x, y); [tup(1,2), tup(3,4), tup(5,6), ...]) {
 void foo(tup(int, string name), string msg);
 (tup(A a, B b)) => a + b;
 switch (tup) { case tup(1, 2): ... }


 This is not very elegant, "tup" becomes a new keyword and generally I
 don't like such strong abbreviations, like the ones used in Rust language,
 but "tuple()" clashes with the library-defined ones, and it's even more
 wordy if you want to define an array of them:

 [tuple(1,2), tuple(3,4), tuple(5,6), ...]

 Bye,
 bearophile

--047d7bd6b2daed753204ddfb8de3 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <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">Regarding the syntax to unpack tuples into single variable= s, Kenji Hara wrote a DIP (<a href=3D"http://wiki.dlang.org/DIP32" target= =3D"_blank">http://wiki.dlang.org/DIP32</a>=A0) denoting tuples with the un= ivesal syntax {...}, but people have found some problems in it.</blockquote=

roblems with Kenji&#39;s proposed syntax?</div><div>Thanks</div><div><br></= div><br><div class=3D"gmail_quote">On Thu, May 30, 2013 at 5:29 AM, bearoph= ile <span dir=3D"ltr">&lt;<a href=3D"mailto:bearophileHUGS lycos.com" targe= t=3D"_blank">bearophileHUGS lycos.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex">Regarding the syntax to unpack tuples into s= ingle variables, Kenji Hara wrote a DIP (<a href=3D"http://wiki.dlang.org/D= IP32" target=3D"_blank">http://wiki.dlang.org/DIP32</a> ) denoting tuples w= ith the univesal syntax {...}, but people have found some problems in it.<b= r> <br> (I think Kenji didn&#39;t update that DIP with all the small improvements w= e suggested in that thread, so they risk getting lost.)<br> <br> Maybe one solution is to use a &quot;tup(...)&quot; syntax, it&#39;s a bit = heavy, but it&#39;s clear and maybe it has no corner cases:<br> <br> tup(int, string) tup =3D tup(1, &quot;hi&quot;);<br> foreach (Float; tup(float, double, real)) { ... }<br> auto tup(x, y) =3D tup(1, &quot;hi&quot;);<br> tup(auto x, y) =3D tup(1, &quot;hi&quot;);<br> tup(int x, string y) =3D tup(1, &quot;hi&quot;);<br> foreach (i, const tup(x, y); [tup(1,2), tup(3,4), tup(5,6), ...]) {<br> void foo(tup(int, string name), string msg);<br> (tup(A a, B b)) =3D&gt; a + b;<br> switch (tup) { case tup(1, 2): ... }<br> <br> <br> This is not very elegant, &quot;tup&quot; becomes a new keyword and general= ly I don&#39;t like such strong abbreviations, like the ones used in Rust l= anguage, but &quot;tuple()&quot; clashes with the library-defined ones, and= it&#39;s even more wordy if you want to define an array of them:<br> <br> [tuple(1,2), tuple(3,4), tuple(5,6), ...]<br> <br> Bye,<br> bearophile<br> </blockquote></div><br> --047d7bd6b2daed753204ddfb8de3--
May 30 2013
prev sibling next sibling parent "deadalnix" <deadalnix gmail.com> writes:
On Friday, 31 May 2013 at 03:07:22 UTC, nazriel wrote:
 That actually looks good...
 I liked idea of:

     auto (x, y) = foo();
     (int x1, string y1) = foo();

     (int, string) foo() {

          (int tmp, string tmp2) = (3, "dsa");

          return (42, "dsa");
     }

 but it was shoot down because of various issues.

This have an issue with one element tuple. Not unsolvable, but must be considered.
 Then proposal with {} risen:

     auto {x, y} = foo();
     {int x1, string y1} = foo();

     {int, string} foo() {

         {int tmp, string tmp2} = {3, "dsa"};

         return {42, "dsa"};
     }

This is a reciepe for disaster. {} are already used way too much, sometime on way that are hard to deambiguate.
 Now this:

     auto #(x, y) = foo();
     #(int x1, string y1) = foo();

     #(int, string) foo() {

         #(int tmp, string tmp2) = #(3, "dsa");

         return #(42, "dsa");
     }

This have the advantage of not having issue with one element tuples.
 My 2 cents :))

 bearophile what do you think?

I also do agree that the 3rd one is probably the best.
May 30 2013
prev sibling next sibling parent "nazriel" <spam dzfl.pl> writes:
 Then proposal with {} risen:

    auto {x, y} = foo();
    {int x1, string y1} = foo();

    {int, string} foo() {

        {int tmp, string tmp2} = {3, "dsa"};

        return {42, "dsa"};
    }

This is a reciepe for disaster. {} are already used way too much, sometime on way that are hard to deambiguate.

I agree.
May 30 2013
prev sibling next sibling parent "w0rp" <devw0rp gmail.com> writes:
On Friday, 31 May 2013 at 04:49:41 UTC, deadalnix wrote:
 On Friday, 31 May 2013 at 03:07:22 UTC, nazriel wrote:
 Now this:

    auto #(x, y) = foo();
    #(int x1, string y1) = foo();

    #(int, string) foo() {

        #(int tmp, string tmp2) = #(3, "dsa");

        return #(42, "dsa");
    }

This have the advantage of not having issue with one element tuples.
 My 2 cents :))

 bearophile what do you think?

I also do agree that the 3rd one is probably the best.

Smalltalk (Also Objective C) went this way long ago, and it worked. http://en.wikipedia.org/wiki/Smalltalk#Literals
May 31 2013
prev sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Friday, 31 May 2013 at 07:32:42 UTC, w0rp wrote:
 On Friday, 31 May 2013 at 04:49:41 UTC, deadalnix wrote:
 On Friday, 31 May 2013 at 03:07:22 UTC, nazriel wrote:
 Now this:

   auto #(x, y) = foo();
   #(int x1, string y1) = foo();

   #(int, string) foo() {

       #(int tmp, string tmp2) = #(3, "dsa");

       return #(42, "dsa");
   }

This have the advantage of not having issue with one element tuples.
 My 2 cents :))

 bearophile what do you think?

I also do agree that the 3rd one is probably the best.

Smalltalk (Also Objective C) went this way long ago, and it worked. http://en.wikipedia.org/wiki/Smalltalk#Literals

Except that in Smalltalk's case, the language is quite similar to Lisp in the sense that its syntax is quite minimalist with most language constructs being achieved by messages. In D you will be adding even more constructs to the grammar.
May 31 2013