digitalmars.D.learn - Why no (auto foo = bar) in while loops?
- Andrej Mitrovic (38/38) Aug 24 2011 Here's some code that iterates through "parents" of some class object
- Timon Gehr (9/47) Aug 24 2011 Afaics, this could be added just like it could be added for if. In fact
- Andrej Mitrovic (2/4) Aug 24 2011 Huh.. How come?
- Timon Gehr (12/16) Aug 24 2011 Well, not notably faster, but many compilers will emit something in the
- Jonathan M Davis (17/42) Aug 24 2011 Optimizations aside, I would always argue that while(true) should be use...
- Timon Gehr (14/56) Aug 24 2011 Well, it is consistent in that you can leave out the other parts in for
- Andrej Mitrovic (1/1) Aug 24 2011 Req'd: http://d.puremagic.com/issues/show_bug.cgi?id=6550
- Mafi (22/79) Aug 24 2011 I just have to say that it already works for 'if'. It's a great feature
- Timon Gehr (13/94) Aug 24 2011 for(;;){int x=init;} // init runs infinitely many times
- Steven Schveighoffer (8/109) Aug 25 2011 I disagree -- I think the semantics are confusing.
- Timon Gehr (5/124) Aug 25 2011 while(condition) do_this;
- Jonathan M Davis (6/135) Aug 25 2011 I don't see why it would be confusing. Because it's unclear whether it's...
- Steven Schveighoffer (32/66) Aug 25 2011 See Mafi's response above.
- Jonathan M Davis (13/97) Aug 25 2011 Well, I'd definitely want it so that x is the value of the condition eve...
- Timon Gehr (30/97) Aug 25 2011 is a
- Steven Schveighoffer (24/50) Aug 25 2011 Not relevant, you are not declaring a variable in your example. The
- Timon Gehr (31/93) Aug 25 2011 It was _the whole point_ that I am not declaring a variable in my
- Steven Schveighoffer (22/124) Aug 25 2011 Except the declaration is not currently allowed in a while-loop
- Timon Gehr (12/146) Aug 25 2011 As an analogy, you said: "We have loops so that we can hide gotos". I
- Ali =?iso-8859-1?q?=C7ehreli?= (24/26) Aug 25 2011 That's a very interesting way of looking at the question.
- Timon Gehr (5/30) Aug 25 2011 Only if it is specifically enabled. The compiler can only rewrite it to
Here's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?
Aug 24 2011
On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:Here's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?Afaics, this could be added just like it could be added for if. In fact the compiler should be able to simply rewrite it to your first example. I think it is worth an enhancement request, because there are situations where this would be useful, and implementation should be trivial, if somebody has the time. (I also think it adds to the consistency of the language, but others may disagree.) (btw, i always use for(;;) instead of while(true), it is usually faster in debug mode and faster to type :))
Aug 24 2011
On 8/24/11, Timon Gehr <timon.gehr gmx.ch> wrote:it is usually faster in debug modeHuh.. How come?
Aug 24 2011
On 08/24/2011 09:21 PM, Andrej Mitrovic wrote:On 8/24/11, Timon Gehr<timon.gehr gmx.ch> wrote:Well, not notably faster, but many compilers will emit something in the lines of mov eax, 1 test eax jnz beginning_of_loop if no optimizer is run, whereas most get for(;;){} as jmp beginning_of_loop even in debug mode.it is usually faster in debug modeHuh.. How come?
Aug 24 2011
On Wednesday, August 24, 2011 21:29:23 Timon Gehr wrote:On 08/24/2011 09:21 PM, Andrej Mitrovic wrote:Optimizations aside, I would always argue that while(true) should be used rather than for(;;). I find for(;;) to be ugly personally and would argue that while(true) better captures what you're actually doing. A loop with no condition at all is horrible IMHO. It seems completely inconsistent to me that the language would allow you to have a for loop without a condition. Regardless of that, however, I would fully expect that if there is a difference in code between the two in debug mode (which there shouldn't be IMHO, but compilers don't always do what makes the most sense - especially in debug mode) that the difference would be drowned by the contents of the loop and wouldn't matter at all. But even if it did, I'd generally argue that coding in a certain way just because it was slightly faster in debug mode but had zero impact in release mode is not a good idea unless all of the considerations are equal. And I'd definitely argue that while(true) is better than for(;;) from an aesthetic point of view at minimum, so they definitely aren't equal. In any case, that's my take on it. - Jonathan M DavisOn 8/24/11, Timon Gehr<timon.gehr gmx.ch> wrote:Well, not notably faster, but many compilers will emit something in the lines of mov eax, 1 test eax jnz beginning_of_loop if no optimizer is run, whereas most get for(;;){} as jmp beginning_of_loop even in debug mode.it is usually faster in debug modeHuh.. How come?
Aug 24 2011
On 08/24/2011 09:36 PM, Jonathan M Davis wrote:On Wednesday, August 24, 2011 21:29:23 Timon Gehr wrote:Well, it is consistent in that you can leave out the other parts in for too. (but those are statements, and you can almost everywhere write an empty statement, while there exist no empty expressions) As to while(true) vs for(;;), in my point of view, it is the other way round, because how it is compiled in debug mode is really how the semantics of the language are: look at the condition, and if it is true, loop another time, if it is false, break. If you want an infinite loop, why bother having to write a condition to evaluate? Imho for(;;){} captures the meaning better than while(true){}. for(;;){} means, loop unconditionally (which proves insight in what it is actually doing), and while(true){} means 'loop until true is false', which is imo ugly for obvious reasons. That is my way of thinking about aesthetics in programming.On 08/24/2011 09:21 PM, Andrej Mitrovic wrote:Optimizations aside, I would always argue that while(true) should be used rather than for(;;). I find for(;;) to be ugly personally and would argue that while(true) better captures what you're actually doing. A loop with no condition at all is horrible IMHO. It seems completely inconsistent to me that the language would allow you to have a for loop without a condition. Regardless of that, however, I would fully expect that if there is a difference in code between the two in debug mode (which there shouldn't be IMHO, but compilers don't always do what makes the most sense - especially in debug mode) that the difference would be drowned by the contents of the loop and wouldn't matter at all. But even if it did, I'd generally argue that coding in a certain way just because it was slightly faster in debug mode but had zero impact in release mode is not a good idea unless all of the considerations are equal. And I'd definitely argue that while(true) is better than for(;;) from an aesthetic point of view at minimum, so they definitely aren't equal. In any case, that's my take on it. - Jonathan M DavisOn 8/24/11, Timon Gehr<timon.gehr gmx.ch> wrote:Well, not notably faster, but many compilers will emit something in the lines of mov eax, 1 test eax jnz beginning_of_loop if no optimizer is run, whereas most get for(;;){} as jmp beginning_of_loop even in debug mode.it is usually faster in debug modeHuh.. How come?
Aug 24 2011
Req'd: http://d.puremagic.com/issues/show_bug.cgi?id=6550
Aug 24 2011
Am 24.08.2011 21:04, schrieb Timon Gehr:On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:I just have to say that it already works for 'if'. It's a great feature because in the body of the 'if' you know the value is non-null and outside, where there could be an segfault, the variable is not visible. I'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for such a construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */ auto obj = init; while(obj) { work(obj); } This could confuse many people, I think. What do you think? MafiHere's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?Afaics, this could be added just like it could be added for if. In fact the compiler should be able to simply rewrite it to your first example. I think it is worth an enhancement request, because there are situations where this would be useful, and implementation should be trivial, if somebody has the time. (I also think it adds to the consistency of the language, but others may disagree.) (btw, i always use for(;;) instead of while(true), it is usually faster in debug mode and faster to type :))
Aug 24 2011
On 08/25/2011 12:47 AM, Mafi wrote:Am 24.08.2011 21:04, schrieb Timon Gehr:for(;;){int x=init;} // init runs infinitely many times if(auto a=init){} is really more trying to solve if(???){auto a=init;} // correct scoping but cannot refer to it in cond than {auto a=init; if(a){}} // correct scoping as long as there is no else That is why there is the language construct. That it has not been adopted for while is because it is so much more useful for if, but I personally think while could/should get the possibility as well.On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:I just have to say that it already works for 'if'. It's a great feature because in the body of the 'if' you know the value is non-null and outside, where there could be an segfault, the variable is not visible. I'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for such a construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */Here's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?Afaics, this could be added just like it could be added for if. In fact the compiler should be able to simply rewrite it to your first example. I think it is worth an enhancement request, because there are situations where this would be useful, and implementation should be trivial, if somebody has the time. (I also think it adds to the consistency of the language, but others may disagree.) (btw, i always use for(;;) instead of while(true), it is usually faster in debug mode and faster to type :))auto obj = init; while(obj) { work(obj); } This could confuse many people, I think. What do you think?I think that by the same argument, you could say that the fact that the body of a looping statement is executed multiple times could confuse many people. 1 is more natural imho. (and 2 would be rather useless)
Aug 24 2011
On Wed, 24 Aug 2011 19:01:31 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:On 08/25/2011 12:47 AM, Mafi wrote:I disagree -- I think the semantics are confusing. I'd say just leave the auto x = y for if and for loops, where there is a clear "run once" section. Also, what do you do with a do while loop if the while contains this construct? I just find the whole thing confusing. -SteveAm 24.08.2011 21:04, schrieb Timon Gehr:for(;;){int x=init;} // init runs infinitely many times if(auto a=init){} is really more trying to solve if(???){auto a=init;} // correct scoping but cannot refer to it in cond than {auto a=init; if(a){}} // correct scoping as long as there is no else That is why there is the language construct. That it has not been adopted for while is because it is so much more useful for if, but I personally think while could/should get the possibility as well.On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:I just have to say that it already works for 'if'. It's a great feature because in the body of the 'if' you know the value is non-null and outside, where there could be an segfault, the variable is not visible. I'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for such a construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */Here's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?Afaics, this could be added just like it could be added for if. In fact the compiler should be able to simply rewrite it to your first example. I think it is worth an enhancement request, because there are situations where this would be useful, and implementation should be trivial, if somebody has the time. (I also think it adds to the consistency of the language, but others may disagree.) (btw, i always use for(;;) instead of while(true), it is usually faster in debug mode and faster to type :))auto obj = init; while(obj) { work(obj); } This could confuse many people, I think. What do you think?I think that by the same argument, you could say that the fact that the body of a looping statement is executed multiple times could confuse many people. 1 is more natural imho. (and 2 would be rather useless)
Aug 25 2011
On 08/25/2011 01:11 PM, Steven Schveighoffer wrote:On Wed, 24 Aug 2011 19:01:31 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:while(condition) do_this; while(auto d=condition) do_this_and_use_d; I still think it is simple, but it is not a feature I miss often.On 08/25/2011 12:47 AM, Mafi wrote:I disagree -- I think the semantics are confusing.Am 24.08.2011 21:04, schrieb Timon Gehr:for(;;){int x=init;} // init runs infinitely many times if(auto a=init){} is really more trying to solve if(???){auto a=init;} // correct scoping but cannot refer to it in cond than {auto a=init; if(a){}} // correct scoping as long as there is no else That is why there is the language construct. That it has not been adopted for while is because it is so much more useful for if, but I personally think while could/should get the possibility as well.On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:I just have to say that it already works for 'if'. It's a great feature because in the body of the 'if' you know the value is non-null and outside, where there could be an segfault, the variable is not visible. I'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for such a construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */Here's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?Afaics, this could be added just like it could be added for if. In fact the compiler should be able to simply rewrite it to your first example. I think it is worth an enhancement request, because there are situations where this would be useful, and implementation should be trivial, if somebody has the time. (I also think it adds to the consistency of the language, but others may disagree.) (btw, i always use for(;;) instead of while(true), it is usually faster in debug mode and faster to type :))auto obj = init; while(obj) { work(obj); } This could confuse many people, I think. What do you think?I think that by the same argument, you could say that the fact that the body of a looping statement is executed multiple times could confuse many people. 1 is more natural imho. (and 2 would be rather useless)I'd say just leave the auto x = y for if and for loops, where there is a clear "run once" section. Also, what do you do with a do while loop if the while contains this construct?In do while it is useless because the scope ends after the condition.
Aug 25 2011
On Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:On Wed, 24 Aug 2011 19:01:31 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:I don't see why it would be confusing. Because it's unclear whether it's set every time or whether it's a new variable every time? It's actually one of those things that I do periodically thinking that it works and then get frustrated when it doesn't, so I'd love to see it added. - Jonathan M DavisOn 08/25/2011 12:47 AM, Mafi wrote:I disagree -- I think the semantics are confusing. I'd say just leave the auto x = y for if and for loops, where there is a clear "run once" section. Also, what do you do with a do while loop if the while contains this construct? I just find the whole thing confusing.Am 24.08.2011 21:04, schrieb Timon Gehr:for(;;){int x=init;} // init runs infinitely many times if(auto a=init){} is really more trying to solve if(???){auto a=init;} // correct scoping but cannot refer to it in cond than {auto a=init; if(a){}} // correct scoping as long as there is no else That is why there is the language construct. That it has not been adopted for while is because it is so much more useful for if, but I personally think while could/should get the possibility as well.On 08/24/2011 08:04 PM, Andrej Mitrovic wrote:I just have to say that it already works for 'if'. It's a great feature because in the body of the 'if' you know the value is non-null and outside, where there could be an segfault, the variable is not visible. I'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for such a construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */Here's some code that iterates through "parents" of some class object until it finds an object with no parent (where parent is null): import std.stdio; class Foo { Foo parent; int state; this (int state) { this.state = state; } } void main() { auto foo = new Foo(0); foo.parent = new Foo(1); foo.parent.parent = new Foo(2); while (true) { if (auto par = foo.parent) { writeln(par.state); foo = par; } else { break; } } } (syntax-highlighted: http://codepad.org/8yHRmICh) But I was hoping I could simplify this by doing: while (auto par = foo.parent) { writeln(par.state); foo = par; } However that doesn't work, I get back: expression expected, not 'auto' Is there a limitation on why this couldn't work or can this be added to the language?Afaics, this could be added just like it could be added for if. In fact the compiler should be able to simply rewrite it to your first example. I think it is worth an enhancement request, because there are situations where this would be useful, and implementation should be trivial, if somebody has the time. (I also think it adds to the consistency of the language, but others may disagree.) (btw, i always use for(;;) instead of while(true), it is usually faster in debug mode and faster to type :))auto obj = init; while(obj) { work(obj); } This could confuse many people, I think. What do you think?I think that by the same argument, you could say that the fact that the body of a looping statement is executed multiple times could confuse many people. 1 is more natural imho. (and 2 would be rather useless)
Aug 25 2011
On Thu, 25 Aug 2011 11:15:44 -0400, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:On 08/25/2011 12:47 AM, Mafi wrote:See Mafi's response above. What it boils down to is, I usually replace code like this: auto x = condition; if(x) { // use x } with this: if(auto x = condition) { // use x. } so the logical mapping to while would map this: auto x = condition; while(x) { // use x. } to this: while(auto x = condition) { // use x. } But it looks like every time through the loop x gets reassigned to condition. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model. -SteveI don't see why it would be confusing. Because it's unclear whether it's set every time or whether it's a new variable every time? It's actually one of those things that I do periodically thinking that it works and then get frustrated when it doesn't, so I'd love to see it added.aI'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for suchI'd say just leave the auto x = y for if and for loops, where there is a clear "run once" section. Also, what do you do with a do while loop if the while contains this construct? I just find the whole thing confusing.construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */
Aug 25 2011
On Thursday, August 25, 2011 11:31:56 Steven Schveighoffer wrote:On Thu, 25 Aug 2011 11:15:44 -0400, Jonathan M Davis <jmdavisProg gmx.com> wrote:Well, I'd definitely want it so that x is the value of the condition every time, and it surprises me that anyone would have thought that that would do anything else. The whole point of creating the variable in the if or while condition like that IMHO is so that you can save what the exact condition was for that run of the if statement or while loop without having to have to run the condition twice or have the variable exist outside the scope of the if- statement or while-loop. If you wanted it to just be the value of the condition on the first iteration, then for does that already quite explicitly. But then again, assuming that for allows you to assign in the condition as well, then at least it's more explicit there, but I would have thought that the semantics of the while loop would have been quite clear. - Jonathan M DavisOn Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:See Mafi's response above. What it boils down to is, I usually replace code like this: auto x = condition; if(x) { // use x } with this: if(auto x = condition) { // use x. } so the logical mapping to while would map this: auto x = condition; while(x) { // use x. } to this: while(auto x = condition) { // use x. } But it looks like every time through the loop x gets reassigned to condition. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model.I don't see why it would be confusing. Because it's unclear whether it's set every time or whether it's a new variable every time? It's actually one of those things that I do periodically thinking that it works and then get frustrated when it doesn't, so I'd love to see it added.On 08/25/2011 12:47 AM, Mafi wrote:aI'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics for suchI'd say just leave the auto x = y for if and for loops, where there is a clear "run once" section. Also, what do you do with a do while loop if the while contains this construct? I just find the whole thing confusing.construct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like any other init and like in 'for' or 'if') */
Aug 25 2011
On 08/25/2011 05:31 PM, Steven Schveighoffer wrote:On Thu, 25 Aug 2011 11:15:44 -0400, Jonathan M Davis <jmdavisProg gmx.com> wrote:otherOn Thursday, August 25, 2011 07:11:31 Steven Schveighoffer wrote:On 08/25/2011 12:47 AM, Mafi wrote:such aI'm not really sure if it's good for 'while'. I'm unsure because there are two somewhat natural semantics forconstruct. //example //more to the nature of while while(auto obj = init) { work(obj); } //1 (your interpretation) typeof(init) obj; while(obj = init) { work(obj); } //2 /* seems more natural for me because init runs only once (like anyis aI'd say just leave the auto x = y for if and for loops, where thereinit and like in 'for' or 'if') */I usually replace code like this: x++; if(x < 100) { // use x } with this: if(++x < 100) { // use x } so the logical mapping to while would map this: x++; while(x < 100) { // use x. } to this: while(++x < 100) { // use x. } But it looks like every time through the loop x gets incremented. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model. Let's ditch the while loop. -TimonSee Mafi's response above. What it boils down to is, I usually replace code like this: auto x = condition; if(x) { // use x } with this: if(auto x = condition) { // use x. } so the logical mapping to while would map this: auto x = condition; while(x) { // use x. } to this: while(auto x = condition) { // use x. } But it looks like every time through the loop x gets reassigned to condition. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model. -Steveclear "run once" section. Also, what do you do with a do while loop if the while contains this construct? I just find the whole thing confusing.I don't see why it would be confusing. Because it's unclear whether it's set every time or whether it's a new variable every time? It's actually one of those things that I do periodically thinking that it works and then get frustrated when it doesn't, so I'd love to see it added.
Aug 25 2011
On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:I usually replace code like this: x++; if(x < 100) { // use x } with this: if(++x < 100) { // use x } so the logical mapping to while would map this: x++; while(x < 100) { // use x. } to this: while(++x < 100) { // use x. } But it looks like every time through the loop x gets incremented. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model. Let's ditch the while loop.Not relevant, you are not declaring a variable in your example. The benefit of using the auto x = y is that you can move the declaration of the variable, which is used only during the loop, into the loop statement. I have written loops like this: bool found = false; while(!found) { // things that might set found to true } There is also this construct, which is what you are arguing for: bool continueloop; while(continueloop = someComplexFunction()) { // use continueloop as rvalue in places } So there are legitimate cases for while(auto x = y) being a shortcut for both behaviors, hence the confusion. I agree your case yields more fruit, since I think the above is actually invalid (can't use = as a boolean expression), but it doesn't stop me from being confused about whether the initialization happens once or every time. It just reads like it happens once to me, even if it happens every loop. That confusion isn't there for if statements or for loops. -Steve
Aug 25 2011
On 08/25/2011 10:51 PM, Steven Schveighoffer wrote:On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:It was _the whole point_ that I am not declaring a variable in my example. Our two examples are equivalent in what they are saying on a conceptual level. Whether the condition contains a declaration or an increment operation does not matter.I usually replace code like this: x++; if(x < 100) { // use x } with this: if(++x < 100) { // use x } so the logical mapping to while would map this: x++; while(x < 100) { // use x. } to this: while(++x < 100) { // use x. } But it looks like every time through the loop x gets incremented. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model. Let's ditch the while loop.Not relevant, you are not declaring a variable in your example.The benefit of using the auto x = y is that you can move the declaration of the variable, which is used only during the loop, into the loopstatement. The benefit of using the auto x = y is that you can declare a new variable inside the condition, plus useful scoping.I have written loops like this: bool found = false; while(!found) { // things that might set found to true }for(;;) { ... break; ... } or even for(bool found=false;!found;){ // things that might set found to true }There is also this construct, which is what you are arguing for: bool continueloop; while(continueloop = someComplexFunction()) { // use continueloop as rvalue in places }I am not arguing for this esoteric case, I wouldn't use a boolean flag, but a reference or pointer that is then guaranteed to be non-null inside each loop body execution. Pragmatic and consistent with how it would normally be used in if.So there are legitimate cases for while(auto x = y) being a shortcut for both behaviors, hence the confusion.There is really no legitimate reason for while(auto x = y) being a shortcut for the first.I agree your case yields more fruit, since I think the above is actually invalid (can't use = as a boolean expression), but it doesn't stop me from being confused about whether the initialization happens once or every time. It just reads like it happens once to me, even if it happens every loop. That confusion isn't there for if statements or for loops.Why does the _loop condition_ read like it happens only once to you? I don't get that. for(init; condition; statement){} while( condition ){} The init part of for is irrelevant for this discussion because it does not exist in while. conditions work for both kinds of loops in the same way: They are executed and checked before the loop body is run. The body of an if is only executed once, therefore the condition is only executed and checked once. If there is an inline-declaration or not does not matter for the execution semantics, and it *WOULD* be confusing if it was.
Aug 25 2011
On Thu, 25 Aug 2011 17:31:26 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:On 08/25/2011 10:51 PM, Steven Schveighoffer wrote: > On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr <timon.gehr gmx.ch> wrote: > > >> >> I usually replace code like this: >> >> x++; >> if(x < 100) >> { >> // use x >> } >> >> with this: >> >> if(++x < 100) { >> // use x >> } >> >> so the logical mapping to while would map this: >> >> x++; >> while(x < 100) >> { >> // use x. >> } >> >> to this: >> >> while(++x < 100) { >> // use x. >> } >> >> >> But it looks like every time through the loop x gets incremented. >> That's not what I'd want. At the very least, it's confusing >> semantics one way or the other. >> >> If you use the construct in the *init* section of a for loop, it reads >> the same as the if statement, since that part is only executed once. >> >> The while loop just doesn't fit the model. Let's ditch the while loop. > > Not relevant, you are not declaring a variable in your example. It was _the whole point_ that I am not declaring a variable in my example. Our two examples are equivalent in what they are saying on a conceptual level. Whether the condition contains a declaration or an increment operation does not matter.Except the declaration is not currently allowed in a while-loop conditional expression. Nor was it allowed in an if conditional expression, until it was added. Prior to that addition, it was necessary to declare the variable outside the if statement in order to only call the intializer once.> The > benefit of using the auto x = y is that you can move the declaration of > the variable, which is used only during the loop, into the loop statement. The benefit of using the auto x = y is that you can declare a new variable inside the condition, plus useful scoping.I think you just said the same thing I did :)> > I have written loops like this: > > bool found = false; > while(!found) > { > // things that might set found to true > } for(;;) { ... break; ... }This doesn't always work, you may need to delay exiting the loop.or even for(bool found=false;!found;){ // things that might set found to true }This also works in your case too. You can simply declare your variable, then assign it in the condition. Insert whatever case you wish there.> > There is also this construct, which is what you are arguing for: > > bool continueloop; > while(continueloop = someComplexFunction()) > { > // use continueloop as rvalue in places > } > I am not arguing for this esoteric case, I wouldn't use a boolean flag, but a reference or pointer that is then guaranteed to be non-null inside each loop body execution. Pragmatic and consistent with how it would normally be used in if.Well, it was just a contrived example, not a full-fledged program.> So there are legitimate cases for while(auto x = y) being a shortcut for > both behaviors, hence the confusion. There is really no legitimate reason for while(auto x = y) being a shortcut for the first.I disagree, especially since it *reads* that way to me.> > I agree your case yields more fruit, since I think the above is actually > invalid (can't use = as a boolean expression), but it doesn't stop me > from being confused about whether the initialization happens once or > every time. It just reads like it happens once to me, even if it happens > every loop. That confusion isn't there for if statements or for loops. > Why does the _loop condition_ read like it happens only once to you? I don't get that.Because it is a declaration. Declarations do not typically get executed more than once, unless it is *inside* a loop. I'm not saying the functionality you want to create is not useful, or that it would not help in many cases. I'm not saying it should be either my way or your way. I'm saying, it *reads* like it could be both ways, and therefore is confusing, and not worth adding to the language. It will lead to people expecting one case, even though it means the other, no matter which way you choose it to mean. We already have several people split about evenly on what they expect. -Steve
Aug 25 2011
On 08/26/2011 12:38 AM, Steven Schveighoffer wrote:On Thu, 25 Aug 2011 17:31:26 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:As an analogy, you said: "We have loops so that we can hide gotos". I said: "We have loops so that we can execute code sequences multiple times". :)On 08/25/2011 10:51 PM, Steven Schveighoffer wrote:Except the declaration is not currently allowed in a while-loop conditional expression. Nor was it allowed in an if conditional expression, until it was added. Prior to that addition, it was necessary to declare the variable outside the if statement in order to only call the intializer once.On Thu, 25 Aug 2011 12:21:19 -0400, Timon Gehr <timon.gehr gmx.ch>wrote:It was _the whole point_ that I am not declaring a variable in my example. Our two examples are equivalent in what they are saying on a conceptual level. Whether the condition contains a declaration or an increment operation does not matter.I usually replace code like this: x++; if(x < 100) { // use x } with this: if(++x < 100) { // use x } so the logical mapping to while would map this: x++; while(x < 100) { // use x. } to this: while(++x < 100) { // use x. } But it looks like every time through the loop x gets incremented. That's not what I'd want. At the very least, it's confusing semantics one way or the other. If you use the construct in the *init* section of a for loop, it reads the same as the if statement, since that part is only executed once. The while loop just doesn't fit the model. Let's ditch the while loop.Not relevant, you are not declaring a variable in your example.I think you just said the same thing I did :)The benefit of using the auto x = y is that you can move the declaration of the variable, which is used only during the loop, into the loopstatement. The benefit of using the auto x = y is that you can declare a new variable inside the condition, plus useful scoping.Yes, but then I don't get type inference, which is not very D-like.This doesn't always work, you may need to delay exiting the loop.I have written loops like this: bool found = false; while(!found) { // things that might set found to true }for(;;) { ... break; ... }or even for(bool found=false;!found;){ // things that might set found to true }This also works in your case too. You can simply declare your variable, then assign it in the condition. Insert whatever case you wish there.I suggest you reconsider.Well, it was just a contrived example, not a full-fledged program.There is also this construct, which is what you are arguing for: bool continueloop; while(continueloop = someComplexFunction()) { // use continueloop as rvalue in places }I am not arguing for this esoteric case, I wouldn't use a boolean flag, but a reference or pointer that is then guaranteed to be non-null inside each loop body execution. Pragmatic and consistent with how it would normally be used in if.I disagree, especially since it *reads* that way to me.So there are legitimate cases for while(auto x = y) being a shortcutforboth behaviors, hence the confusion.There is really no legitimate reason for while(auto x = y) being a shortcut for the first.while(condition) statement; ~~~~~~~~~~~~~~~~~~~~~~~ ^- inside loop How can you say the condition is not part of the loop? It is looped too.Because it is a declaration. Declarations do not typically get executed more than once, unless it is *inside* a loop.I agree your case yields more fruit, since I think the above isactuallyinvalid (can't use = as a boolean expression), but it doesn't stop me from being confused about whether the initialization happens once or every time. It just reads like it happens once to me, even if ithappensevery loop. That confusion isn't there for if statements or for loops.Why does the _loop condition_ read like it happens only once to you? I don't get that.I'm not saying the functionality you want to create is not useful, or that it would not help in many cases. I'm not saying it should be either my way or your way. I'm saying, it *reads* like it could be both ways, and therefore is confusing, and not worth adding to the language. It will lead to people expecting one case, even though it means the other, no matter which way you choose it to mean. We already have several people split about evenly on what they expect. -SteveWell, I don't get it. If I ever write a D compiler, this feature will be supported. =)
Aug 25 2011
On Thu, 25 Aug 2011 23:31:26 +0200, Timon Gehr wrote:for(init; condition; statement){} while( condition ){}That's a very interesting way of looking at the question. I bet that explains the other way around: there can't be a variable definition in the 'for' loop's condition clause, because 'while' doesn't allow it. :p The compiler probably uses 'while's implementation. The 'for' loop probably becomes this: { for_init; while (for_condition) { for_body; for_statement; } } So there is no discrepancy: the condition clauses cannot define a variable in either loop. :) If 'while' gets this enhancement, 'for' could be written as the following: for (int i = 0; auto c = condition(); ++i) { // Yes, we know that c doesn't evaluate to 'false', but // we can use c here when it evaluates to 'true'. // e.g. if it's a pointer: writeln(*c); } Ali
Aug 25 2011
On 08/26/2011 02:00 AM, Ali Çehreli wrote:On Thu, 25 Aug 2011 23:31:26 +0200, Timon Gehr wrote:There is a little discrepancy because 'if' condition clauses can. ;)for(init; condition; statement){} while( condition ){}That's a very interesting way of looking at the question. I bet that explains the other way around: there can't be a variable definition in the 'for' loop's condition clause, because 'while' doesn't allow it. :p The compiler probably uses 'while's implementation. The 'for' loop probably becomes this: { for_init; while (for_condition) { for_body; for_statement; } } So there is no discrepancy: the condition clauses cannot define a variable in either loop. :)If 'while' gets this enhancement, 'for' could be written as the following: for (int i = 0; auto c = condition(); ++i) { // Yes, we know that c doesn't evaluate to 'false', but // we can use c here when it evaluates to 'true'. // e.g. if it's a pointer: writeln(*c); }Only if it is specifically enabled. The compiler can only rewrite it to the while form if it can successfully parse it. But I think that indeed iff while is enhanced, for should be too.
Aug 25 2011