www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Feature request: extending comma operator's functionality

reply "Tommi" <tommitissari hotmail.com> writes:
Could you change it so that expressions, that are separated by 
commas and inside an if-clause, would have visibility to the 
variable defined in the first expression? Easier to show than to 
explain:

int getInt()
{
     return 11;
}

void main()
{
     if (int n = getInt(), n > 10) // undefined identifier n
     {
         //...
     }

     if (int n = getInt(), ++n, n > 10) // undefined identifier n
     {
         //...
     }

     if (int n = getInt(), getInt() > 10) // OK
     {
         //...
     }
}

That would make it possible to define variables in the smallest 
possible scope, and not pollute the namespace of the enclosing 
scope.
Oct 04 2012
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 4 October 2012 at 21:17:51 UTC, Tommi wrote:
 Could you change it so that expressions, that are separated by 
 commas and inside an if-clause, would have visibility to the 
 variable defined in the first expression? Easier to show than 
 to explain:
 [SNIP]

A language change sounds excessive for something that simple blocks could fix: int getInt() { return 11; } void main() { { int n = getInt(); if (n > 10) // OK { //... } } { int n = getInt(); ++n; if (n > 10) // OK { //... } } { int n = getInt(); if (getInt() > 10) // OK { //... } } } Been doing this in C++ for a while actually.
Oct 04 2012
prev sibling next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, October 04, 2012 23:11:58 Tommi wrote:
 Could you change it so that expressions, that are separated by
 commas and inside an if-clause, would have visibility to the
 variable defined in the first expression? Easier to show than to
 explain:
 
 int getInt()
 {
 return 11;
 }
 
 void main()
 {
 if (int n = getInt(), n > 10) // undefined identifier n
 {
 //...
 }
 
 if (int n = getInt(), ++n, n > 10) // undefined identifier n
 {
 //...
 }
 
 if (int n = getInt(), getInt() > 10) // OK
 {
 //...
 }
 }
 
 That would make it possible to define variables in the smallest
 possible scope, and not pollute the namespace of the enclosing
 scope.

If you want to restrict the scope of a variable, you can simply use another set of braces to create a new scope. It might be more verbose than desirable, but it works just fine. e.g. { int n = getInt(); if(n > 10) { ... } } As it stands, there's a good chance that the comma operator is actually going to be _removed_ from the language (aside from specific use cases such as inside for loops). So, I don't think that there's much chance of it being expanded at all. - Jonathan M Davis
Oct 04 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/04/2012 11:56 PM, Tommi wrote:
 On Thursday, 4 October 2012 at 21:32:34 UTC, Jonathan M Davis wrote:
 If you want to restrict the scope of a variable, you can simply use
 another set of braces to create a new scope. It might be more verbose
 than desirable, but it works just fine. e.g.

 {
  int n = getInt();
  if(n > 10)
  {
  ...
  }
 }

But if there are else-if clauses, then you end up polluting your namespace, and notice how the syntax of your workaround deteriorates exponentially: ...

Check your math.
Oct 05 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Thursday, 4 October 2012 at 21:32:34 UTC, Jonathan M Davis 
wrote:
 If you want to restrict the scope of a variable, you can simply 
 use another set of braces to create a new scope. It might be 
 more verbose than desirable, but it works just fine. e.g.

 {
  int n = getInt();
  if(n > 10)
  {
  ...
  }
 }

But if there are else-if clauses, then you end up polluting your namespace, and notice how the syntax of your workaround deteriorates exponentially: The extended if-clause syntax: ------------------------------ if (byte n = fun1(), n > 10) { //... } else if (int n = fun2(), n > 100) { //... } else if (ulong n = fun3(), n > 1000) { //... } The workaround syntax: ---------------------- { byte n1 = fun1(); if (n1 > 10) { //... } else { int n2 = fun2(); if (n2 > 100) { //... } else { ulong n3 = fun3(); if (n3 > 1000) { //... } } } }
 As it stands, there's a good chance that the comma operator is 
 actually going to be _removed_ from the language (aside from 
 specific use cases such as inside for loops). So, I don't think
 that there's much chance of it being expanded at all.

I don't see a problem there. I mean, if the comma operator is kept in specific cases like inside for loop, why not keep (and expand it's use) it in this specific case of if-clause.
Oct 04 2012
prev sibling next sibling parent "David Nadlinger" <see klickverbot.at> writes:
On Thursday, 4 October 2012 at 21:17:51 UTC, Tommi wrote:
 Could you change it so that expressions, that are separated by 
 commas and inside an if-clause, would have visibility to the 
 variable defined in the first expression?

Yes, a language designed could make that choice. But not, it certainly won't be considered for D unless it can be shown that the change solves a real problem with the current syntax. And how often have you really encountered big syntactic headaches because of not having something like this available? David
Oct 04 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Thursday, 4 October 2012 at 22:28:24 UTC, David Nadlinger 
wrote:
 Yes, a language designed could make that choice. But not, it 
 certainly won't be considered for D unless it can be shown that 
 the change solves a real problem with the current syntax.

But I'm not suggesting any kind of change in syntax. This syntax in D currently works (as long as expr2 is convertible to bool): if (Type var = expr1, expr2) { //... } What I'm suggesting is, I think, quite reasonable: make it so that 'var' is visible to 'expr2'.
Oct 04 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 4 October 2012 at 22:28:24 UTC, David Nadlinger 
wrote:
 how often have you really encountered big syntactic headaches 
 because of not having something like this available?

I do somewhat regularly. The if(auto x = y()) { use x } is pretty convenient but being limited only to the bool check is kinda weak.
Oct 04 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Thursday, 4 October 2012 at 22:36:47 UTC, Tommi wrote:
 But I'm not suggesting any kind of change in syntax. This 
 syntax in D currently works (as long as expr2 is convertible to 
 bool):

 if (Type var = expr1, expr2)
 {
     //...
 }

 What I'm suggesting is, I think, quite reasonable: make it so 
 that 'var' is visible to 'expr2'.

Uh... I was actually wrong. What that syntax really does is this: if (Type var = cast(Type)expr2) { //... } Didn't see that coming. But I think it might be a bug, because assignment expression has precedence over sequencing expression, that is, expressions separated by commas.
Oct 04 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Thursday, 4 October 2012 at 23:16:53 UTC, Tommi wrote:
 Didn't see that coming. But I think it might be a bug, because 
 assignment expression has precedence over sequencing 
 expression, that is, expressions separated by commas.

Although that's not an assignment expression, but a variable definition. I think the following should be a bug then (currently): if (int val = 123, true) { //... } Because the following is a bug: int val = 123, true; // Error: no identifier for declarator int // Error: semicolon expected, not 'true'
Oct 04 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, October 04, 2012 23:56:15 Tommi wrote:
 As it stands, there's a good chance that the comma operator is
 actually going to be _removed_ from the language (aside from
 specific use cases such as inside for loops). So, I don't think
 that there's much chance of it being expanded at all.

I don't see a problem there. I mean, if the comma operator is kept in specific cases like inside for loop, why not keep (and expand it's use) it in this specific case of if-clause.

You will have a hard sell with _anything_ involving commas other than tuples. Most people consider anything like the comma operator to be evil (or at least very undesirable). - Jonathan M Davis
Oct 04 2012
prev sibling next sibling parent reply "Tommi" <tommitissari hotmail.com> writes:
Maybe we forget about commas then, and extend if-clauses so that 
you can properly define variables at the beginning of it. 
Separated by semicolons.

string name;

if (string street = nextStreet();
     int number = nextNumber();
     auto person = new Person(name);

     person.livesAt(number, street))
{
     // use street, number, and person
}
Oct 04 2012
next sibling parent reply Don Clugston <dac nospam.com> writes:
On 05/10/12 15:35, monarch_dodra wrote:
 On Friday, 5 October 2012 at 00:22:04 UTC, Jonathan M Davis wrote:
 On Friday, October 05, 2012 02:08:14 bearophile wrote:
 [SNIP]
 Regarding definition of variables in D language constructs, there
 is one situation where sometimes I find D not handy. This code
 can't work:

 do {
 const x = ...;
 } while (predicate(x));


 You need to use:

 T x;
 do {
 x = ...;
 } while (predicate(x));

Yeah. That comes from C/C++ (and is the same in Java and C#, I believe). I don't know why it works that way. It's definitely annoying. [SNIP] - Jonathan M Davis

Because it's the only way to guarantee that x exits when you reach the end of the loop. do { if(true) continue; //Yawn... skip. const x = ... ; } while (predicate(x)); //What's x? Basic goto limitations. Unlike goto though, inserting a "continue" should never create a compile error, so the compiler *has* to guarantee that the if condition references nothing inside its own block. It is annoying, but nothing that can't be fixed with a scope bloc.

My feeling is that do{}while() is a fairly useless concept, and this is part of the reason. In my experience genuine do-while loops are extremely rare, and it only takes a slight change to the loop to force a different structure to be used. Conditional loops which don't follow the while(){...} pattern normally follow the loop-and-a-half pattern, also known as begin-while-repeat (I think that's the name Knuth used). I'll call it 'super do': super do { foo(); while(cond); bar(); } which in D is better modelled by: for (;;) { foo(); if (!cond) break; bar(); } rather than by a do-while loop. But it's a bit ugly, and doesn't enforce a single break. IMHO it's a shame we've gone with the fairly useless do-while, rather than cleaning up the syntax for loop-and-a-half. I don't think the proposed changes bring us much closer to a useful language construct.
Oct 05 2012
parent Don Clugston <dac nospam.com> writes:
On 05/10/12 18:58, H. S. Teoh wrote:
 On Fri, Oct 05, 2012 at 05:23:40PM +0200, Don Clugston wrote:
 [...]
 My feeling is that  do{}while() is a fairly useless concept, and
 this is part of the reason.
 In my experience genuine do-while loops are extremely rare, and it
 only takes a slight change to the loop to force a different
 structure to be used.
 Conditional loops which don't follow the while(){...} pattern
 normally follow the loop-and-a-half pattern, also known as
 begin-while-repeat (I think that's the name Knuth used). I'll call
 it 'super do':

 super do {
     foo();
     while(cond);
     bar();
 }

 which in D is better modelled by:

 for (;;)
 {
     foo();
     if (!cond) break;
     bar();
 }

This isn't "super do", it's just "loop", the way nature intended. ;-) I've always been an advocate of this construct: loop { // initial part of loop body } while(cond) { // exit point // trailing part of loop body }

Looks OK, except that the scopes look wrong. I would hope than a variable declared in the initial part of the body is also visible in the trailing part. The {} don't work properly. Regardless of the syntax, I think it is _the_ fundamental loop construct, and I've always found it odd that most languages don't include it. I first found encountered it in Forth, and have missed it ever since.
 To some extent, D (and C/C++)'s for-loops exhibit a similar structure:

 	for (X; Y; Z) {}

 The trailing part of the loop body corresponds with Z; the condition
 corresponds with Y.

Yes. C got 'for' loops right.
 To avoid the introduction of a new keyword, we may fuse the do-loop and
 the while-loop together:

 	do {
 		...
 	} while (cond) {
 		...
 	}

 The current do-loop is simply a special case of this construct where the
 second {...} is replaced with a ;, and the while-loop is a special case
 of this construct where the initial part of the loop is elided.

 I argue that this generalized construct is much more useful than the
 do-loop or while-loop individually, plus it doesn't break any existing
 code.

I agree that it's more useful. But that code was legal until a couple of releases ago, because a trailing ; was not required on do-while loops. do { xxx; } while(cond) { yyy; } means: do { xxx; } while(cond); yyy; Even without that, it puts a huge significance on that semicolon. So I don't think that works. How about: do { ... do while (cond); ... } ? This is technically already legal too, although 'do while(cond);' is currently either a no-op, or an infinite loop.
Oct 08 2012
prev sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 10/05/2012 03:35 PM, monarch_dodra wrote:
 On Friday, 5 October 2012 at 00:22:04 UTC, Jonathan M Davis wrote:
 On Friday, October 05, 2012 02:08:14 bearophile wrote:
 [SNIP]
 Regarding definition of variables in D language constructs, there
 is one situation where sometimes I find D not handy. This code
 can't work:

 do {
 const x = ...;
 } while (predicate(x));


 You need to use:

 T x;
 do {
 x = ...;
 } while (predicate(x));

Yeah. That comes from C/C++ (and is the same in Java and C#, I believe). I don't know why it works that way. It's definitely annoying. [SNIP] - Jonathan M Davis

Because it's the only way to guarantee that x exits when you reach the end of the loop.

s/only/simplest/
 do {
    if(true) continue; //Yawn... skip.
    const x = ... ;
 } while (predicate(x)); //What's x?

 Basic goto limitations. Unlike goto though, inserting a "continue"
 should never create a compile error, so the compiler *has* to guarantee
 that the if condition references nothing inside its own block.

 It is annoying, but nothing that can't be fixed with a scope bloc.

Oct 07 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, October 05, 2012 00:36:22 Adam D. Ruppe wrote:
 On Thursday, 4 October 2012 at 22:28:24 UTC, David Nadlinger
 
 wrote:
 how often have you really encountered big syntactic headaches
 because of not having something like this available?

I do somewhat regularly. The if(auto x = y()) { use x } is pretty convenient but being limited only to the bool check is kinda weak.

Yeah. It would definitely be useful to be able to do like you do with a for loop with an if, but in that case, I'd probably suggest just making it look like it looks like with for. if(auto x = y(); x != 42) {} That would be really cool, but I expect that it would be hard to talk Walter into it. - Jonathan M Davis
Oct 04 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Tommi:

 Maybe we forget about commas then, and extend if-clauses so 
 that you can properly define variables at the beginning of it. 
 Separated by semicolons.

Regarding definition of variables in D language constructs, there is one situation where sometimes I find D not handy. This code can't work: do { const x = ...; } while (predicate(x)); You need to use: T x; do { x = ...; } while (predicate(x)); Bye, bearophile
Oct 04 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, October 05, 2012 02:08:14 bearophile wrote:
 Tommi:
 Maybe we forget about commas then, and extend if-clauses so
 that you can properly define variables at the beginning of it.
 Separated by semicolons.

Regarding definition of variables in D language constructs, there is one situation where sometimes I find D not handy. This code can't work: do { const x = ...; } while (predicate(x)); You need to use: T x; do { x = ...; } while (predicate(x));

Yeah. That comes from C/C++ (and is the same in Java and C#, I believe). I don't know why it works that way. It's definitely annoying. Of course, changing it at this point would change the semantics in a potentially code-breaking manner in that if the condition relies on any variables local to the loop having been destroyed, then its behavior will change. That's probably an insanely uncommon situation though - enough so that I'd be all for changing the semantics to have the scope exited _after_ the test is done (assuming that there's not a solid technical reason to keep it as-is). But I have no idea how possible it is to talk Walter into that sort of change. - Jonathan M Davis
Oct 04 2012
prev sibling next sibling parent "timotheecour" <thelastmammoth gmail.com> writes:
Is the plan to deprecate comma operator for chaining expressions?
I would love to see more syntactic sugar to support tuples, and 
comma operator would be the best fit for that purpose.

eg:
----
import std.typecons;
auto fun(){
     return tuple(1,"abc");
     //1) ideally, we should be able to write:
     //return (1,"abc");
     //with same semantics (and no need to import std.typecons)
}

//at the call site: currently:
auto t=fun();
auto a=t[0];
auto b=t[1];

//2) ideally, we should be able to write:
auto (a,b,c)=fun();

//3) or even:
(a,b,c)=fun();
----

Will it be difficult to implement 2)? (by far the most important 
of 1,2,3)
Is 1) and 3) a good idea?
Oct 04 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, October 05, 2012 02:33:45 timotheecour wrote:
 Is the plan to deprecate comma operator for chaining expressions?

That's all the comma operator does. If it's not chaining expressions, it's not the comma operator (e.g. variables declarations do _not_ use the comma operator even though they can use commas). There is a proposal to remove the comma operator, altering for loops so that they explicitly support using commas like they currently do but otherwise completely removing the comma operator: http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP19
 I would love to see more syntactic sugar to support tuples, and
 comma operator would be the best fit for that purpose.

That's one of the main reasons for the proposal, but nothing has been decided yet. The discussion is here: http://forum.dlang.org/thread/k3ns2a$1ndc$1 digitalmars.com - Jonathan M Davis
Oct 04 2012
prev sibling next sibling parent "Tove" <tove fransson.se> writes:
On Friday, 5 October 2012 at 00:22:04 UTC, Jonathan M Davis wrote:
 On Friday, October 05, 2012 02:08:14 bearophile wrote:
 Tommi:
 Maybe we forget about commas then, and extend if-clauses so
 that you can properly define variables at the beginning of 
 it.
 Separated by semicolons.

Regarding definition of variables in D language constructs, there is one situation where sometimes I find D not handy. This code can't work: do { const x = ...; } while (predicate(x)); You need to use: T x; do { x = ...; } while (predicate(x));


Don't forget the with statement, it's not "just" for switches! In many cases it's actually even better than the proposed changes _and_ it works today! import std.stdio; struct d_is_beautiful { int a=1; int b=2; } void main() { with(d_is_beautiful()) if(a==1) writeln("ok"); else writeln("ko:", a); with(d_is_beautiful()) do { ++a; writeln("iter"); } while(a!=b); }
Oct 05 2012
prev sibling next sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Friday, 5 October 2012 at 07:26:43 UTC, Tove wrote:
 Don't forget the with statement, it's not "just" for switches! 
 In many cases it's actually even better than the proposed 
 changes _and_ it works today!

I've asked recently to have declaration inside the with statement too (same as if has now)... I don't remember why exactly now but it definitely seemed useful at the time.
Oct 05 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Friday, 5 October 2012 at 07:26:43 UTC, Tove wrote:
 Don't forget the with statement, it's not "just" for switches! 
 In many cases it's actually even better than the proposed 
 changes _and_ it works today!

 import std.stdio;

 struct d_is_beautiful
 {
   int a=1;
   int b=2;
 }

 void main()
 {
   with(d_is_beautiful()) if(a==1)
     writeln("ok");
   else
     writeln("ko:", a);

   with(d_is_beautiful()) do
   {
     ++a;
     writeln("iter");
   }
   while(a!=b);
 }

This was news to me. It seems you can also use a tuple for that. That's a pretty decent workaround: import std.typecons; //... with (Tuple!(int, "a")(getInt())) if (a > 9) { //... } else with (Tuple!(char, "b")(getChar())) if (b == 'D') { //... } On Friday, 5 October 2012 at 07:28:29 UTC, Timon Gehr wrote:
 But if there are else-if clauses, then you end up polluting 
 your namespace, and notice how the syntax of your workaround 
 deteriorates exponentially:
 ...

Check your math.

Correction: "the syntax deteriorates only linearly".
Oct 05 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 5 October 2012 at 00:22:04 UTC, Jonathan M Davis wrote:
 On Friday, October 05, 2012 02:08:14 bearophile wrote:
 [SNIP]
 Regarding definition of variables in D language constructs, 
 there
 is one situation where sometimes I find D not handy. This code
 can't work:
 
 do {
 const x = ...;
 } while (predicate(x));
 
 
 You need to use:

 T x;
 do {
 x = ...;
 } while (predicate(x));

Yeah. That comes from C/C++ (and is the same in Java and C#, I believe). I don't know why it works that way. It's definitely annoying. [SNIP] - Jonathan M Davis

Because it's the only way to guarantee that x exits when you reach the end of the loop. do { if(true) continue; //Yawn... skip. const x = ... ; } while (predicate(x)); //What's x? Basic goto limitations. Unlike goto though, inserting a "continue" should never create a compile error, so the compiler *has* to guarantee that the if condition references nothing inside its own block. It is annoying, but nothing that can't be fixed with a scope bloc.
Oct 05 2012
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Friday, 5 October 2012 at 15:35:31 UTC, Don Clugston wrote:
 My feeling is that  do{}while() is a fairly useless concept...
 [SNIP]

The most frequent use I have for do while is to hack it to construct break-able blocks actually ^^ : //---- do { if(!condition1) break; if(!condition2) break; if(!condition3) break; if(!condition4) break; //DO SOMETHING }while(false); //---- It is a nice way to avoid the dreaded "if(if(if(if(if(if())))))))" triangle. Related: http://d.puremagic.com/issues/show_bug.cgi?id=8622
Oct 05 2012
prev sibling next sibling parent "David Piepgrass" <qwertie256 gmail.com> writes:
 Because it's the only way to guarantee that x exits when you 
 reach the end of the loop.

 do {
   if(true) continue; //Yawn... skip.
   const x = ... ;
 } while (predicate(x)); //What's x?

But the compiler could tell that there is a 'continue' before x was declared, and issue an error when it is used in while(...)
Oct 05 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Oct 05, 2012 at 05:23:40PM +0200, Don Clugston wrote:
[...]
 My feeling is that  do{}while() is a fairly useless concept, and
 this is part of the reason.
 In my experience genuine do-while loops are extremely rare, and it
 only takes a slight change to the loop to force a different
 structure to be used.
 Conditional loops which don't follow the while(){...} pattern
 normally follow the loop-and-a-half pattern, also known as
 begin-while-repeat (I think that's the name Knuth used). I'll call
 it 'super do':
 
 super do {
    foo();
    while(cond);
    bar();
 }
 
 which in D is better modelled by:
 
 for (;;)
 {
    foo();
    if (!cond) break;
    bar();
 }

This isn't "super do", it's just "loop", the way nature intended. ;-) I've always been an advocate of this construct: loop { // initial part of loop body } while(cond) { // exit point // trailing part of loop body } To some extent, D (and C/C++)'s for-loops exhibit a similar structure: for (X; Y; Z) {} The trailing part of the loop body corresponds with Z; the condition corresponds with Y. To avoid the introduction of a new keyword, we may fuse the do-loop and the while-loop together: do { ... } while (cond) { ... } The current do-loop is simply a special case of this construct where the second {...} is replaced with a ;, and the while-loop is a special case of this construct where the initial part of the loop is elided. I argue that this generalized construct is much more useful than the do-loop or while-loop individually, plus it doesn't break any existing code. T -- Без труда не выловишь и рыбку из пруда.
Oct 05 2012
prev sibling next sibling parent "ixid" <nuaccount gmail.com> writes:
On Friday, 5 October 2012 at 00:39:40 UTC, timotheecour wrote:
 Is the plan to deprecate comma operator for chaining 
 expressions?
 I would love to see more syntactic sugar to support tuples, and 
 comma operator would be the best fit for that purpose.

 eg:
 ----
 import std.typecons;
 auto fun(){
     return tuple(1,"abc");
     //1) ideally, we should be able to write:
     //return (1,"abc");
     //with same semantics (and no need to import std.typecons)
 }

 //at the call site: currently:
 auto t=fun();
 auto a=t[0];
 auto b=t[1];

 //2) ideally, we should be able to write:
 auto (a,b,c)=fun();

 //3) or even:
 (a,b,c)=fun();
 ----

 Will it be difficult to implement 2)? (by far the most 
 important of 1,2,3)
 Is 1) and 3) a good idea?

Surely the ideal is what you're written but also allowing the omission of parens where it's unambiguous? Just to keep this idea in people's minds: return 1, "abc"; That would seem like the ideal to me as would: double, string fun(double, double n) { return n[0] * n[1], "abc"; } Should these uses require parens like this? (double, string) fun((double, double) n) { return (n[0] * n[1], "abc"); } As discussed before the parens are unavoidable for assignment given the need to avoid breaking vast quantities of code.
Oct 05 2012
prev sibling parent "Tove" <tove fransson.se> writes:
On Friday, 5 October 2012 at 13:47:00 UTC, monarch_dodra wrote:
 On Friday, 5 October 2012 at 00:22:04 UTC, Jonathan M Davis 
 wrote:
 On Friday, October 05, 2012 02:08:14 bearophile wrote:
 [SNIP]
 Regarding definition of variables in D language constructs, 
 there
 is one situation where sometimes I find D not handy. This code
 can't work:
 
 do {
 const x = ...;
 } while (predicate(x));
 
 
 You need to use:

 T x;
 do {
 x = ...;
 } while (predicate(x));

Yeah. That comes from C/C++ (and is the same in Java and C#, I believe). I don't know why it works that way. It's definitely annoying. [SNIP] - Jonathan M Davis

Because it's the only way to guarantee that x exits when you reach the end of the loop. do { if(true) continue; //Yawn... skip. const x = ... ; } while (predicate(x)); //What's x? Basic goto limitations. Unlike goto though, inserting a "continue" should never create a compile error, so the compiler *has* to guarantee that the if condition references nothing inside its own block. It is annoying, but nothing that can't be fixed with a scope bloc.

There is a simple way around this... which addresses both concerns raised... 1. Semantics of old code is unchanged. 2. no issue with 'continue' do(const x = ...) { } while(predicate(x));
Oct 07 2012