October 05, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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.
| |||
October 05, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 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.
| |||
October 05, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | 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 | |||
October 05, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | > 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(...)
| |||
October 05, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | 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 -- Без труда не выловишь и рыбку из пруда. | |||
October 05, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to timotheecour | 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.
| |||
October 07, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 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));
| |||
October 07, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | 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. | |||
October 08, 2012 Re: Feature request: extending comma operator's functionality | ||||
|---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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. | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply