Thread overview
Regurgitated proposal: Make loop conditions part of the body's scope
Aug 01, 2007
downs
Aug 01, 2007
Bill Baxter
Aug 01, 2007
downs
Aug 02, 2007
Daniel Keep
August 01, 2007
I realize this has been requested before, by me and a few others, gained the votes of a significant amount of people here, been completely ignored by Walter (no offense meant, I know he can't read every proposal), you know how it goes. The reason I'm bringing it up again is that it could potentially, and implicitly, help (or even completely) fix a quite serious bug I discovered this morning.

To recap: the proposal is to make the parameter ("()") part of some common constructs such as while, do/while and with (I'll get to that in a second) part of the scope of the actual loop body - this would allow, for instance, checking the value of an inner variable in the condition of a do/while loop.
Disadvantages: it breaks compatibility with C++ in cases which are forbidden anyway (shadowing declarations). .. That's all I can think of. As far as I know, it doesn't change the behavior of existing code.

Now, for the bug.
Consider the following example program.

scope class test { this() { writefln("this"); } ~this() { writefln("~this"); } }
void main() {
        writefln("Pre");
        with (new test) { writefln("Inside With"); }
        writefln("Post");
}

What would be expected: Pre  this  Inside With  ~this  Post.
What happens: Pre  This  Inside With  Post  ~this.
Okay, I thought, so the new test is in the outside scope. Sucks, but workable. I changed it to

	{ with (new test) { writefln("Inside With"); } }

...
I got the same results.
Turns out constructing an instance of a scoped class as the parameter of a with construct makes the compiler COMPLETELY ignore the scope.
And I can't help thinking, if the with loop's parameters were part of the inner scope, that bug _probably_ wouldn't have happened. Which is why I'm holding off on a bug report until there's some feedback on what the compiler should do in this situation.

With greetings and stuffies,
 --downs
August 01, 2007
downs wrote:
> I realize this has been requested before, by me and a few others, gained the votes of a significant amount of people here, been completely ignored by Walter (no offense meant, I know he can't read every proposal), you know how it goes. The reason I'm bringing it up again is that it could potentially, and implicitly, help (or even completely) fix a quite serious bug I discovered this morning.
> 
> To recap: the proposal is to make the parameter ("()") part of some common constructs such as while, do/while and with (I'll get to that in a second) part of the scope of the actual loop body - this would allow, for instance, checking the value of an inner variable in the condition of a do/while loop.
> Disadvantages: it breaks compatibility with C++ in cases which are forbidden anyway (shadowing declarations). .. That's all I can think of. As far as I know, it doesn't change the behavior of existing code.
> 
> Now, for the bug.
> Consider the following example program.
> 
> scope class test { this() { writefln("this"); } ~this() { writefln("~this"); } }
> void main() {
>         writefln("Pre");
>         with (new test) { writefln("Inside With"); }
>         writefln("Post");
> }
> 
> What would be expected: Pre  this  Inside With  ~this  Post.
> What happens: Pre  This  Inside With  Post  ~this.
> Okay, I thought, so the new test is in the outside scope. Sucks, but workable. I changed it to
> 
>     { with (new test) { writefln("Inside With"); } }
> 
> ...
> I got the same results.
> Turns out constructing an instance of a scoped class as the parameter of a with construct makes the compiler COMPLETELY ignore the scope.
> And I can't help thinking, if the with loop's parameters were part of the inner scope, that bug _probably_ wouldn't have happened. Which is why I'm holding off on a bug report until there's some feedback on what the compiler should do in this situation.
> 
> With greetings and stuffies,
>  --downs


I'm pretty sure variables are within the scope of for loops etc.  At least I'm 99% sure this is Ok:

  for(int i=0;i<10;i++) { writefln(i); }
  for(int i=0;i<10;i++) { writefln(i); }

So the scope of the i *is* limited to just the body of the for loop normally.  'Scope' seems to defeat that somehow.  Actually I thought even with scope classes you still needed to say 'scope' at the point of use or else get an error.  So it could be that the root of the error is that D is letting you create a scope class in a non-scope way, when it shouldn't.

--bb
August 01, 2007
Bill Baxter wrote:
> So it could be that the root of the error is
> that D is letting you create a scope class in a non-scope way, when it shouldn't.
> 
> --bb

Okay, but the behavior I described is what would be expected from constructing a scope object like "with (new ScopeObject)", because "with" *means* "use the parameter inside the scope"; a behavior which is semantically very similar to what "scope" means.
So I'd recommend making this actually a _valid_ case, as well as fixing its behavior, instead of outright forbidding it (which, admittedly, would also solve the bug).
 --downs
August 02, 2007

downs wrote:
> I realize this has been requested before, by me and a few others, gained the votes of a significant amount of people here, been completely ignored by Walter (no offense meant, I know he can't read every proposal), you know how it goes. The reason I'm bringing it up again is that it could potentially, and implicitly, help (or even completely) fix a quite serious bug I discovered this morning.
> 
> To recap: the proposal is to make the parameter ("()") part of some
> common constructs such as while, do/while and with (I'll get to that in
> a second) part of the scope of the actual loop body - this would allow,
> for instance, checking the value of an inner variable in the condition
> of a do/while loop.
> Disadvantages: it breaks compatibility with C++ in cases which are
> forbidden anyway (shadowing declarations). .. That's all I can think of.
> As far as I know, it doesn't change the behavior of existing code.
> 
> Now, for the bug.
> Consider the following example program.
> 
> scope class test { this() { writefln("this"); } ~this() {
> writefln("~this"); } }
> void main() {
>         writefln("Pre");
>         with (new test) { writefln("Inside With"); }
>         writefln("Post");
> }
> 
> What would be expected: Pre  this  Inside With  ~this  Post.
> What happens: Pre  This  Inside With  Post  ~this.
> Okay, I thought, so the new test is in the outside scope. Sucks, but
> workable. I changed it to
> 
>     { with (new test) { writefln("Inside With"); } }
> 
> ....
> I got the same results.
> Turns out constructing an instance of a scoped class as the parameter of
> a with construct makes the compiler COMPLETELY ignore the scope.
> And I can't help thinking, if the with loop's parameters were part of
> the inner scope, that bug _probably_ wouldn't have happened. Which is
> why I'm holding off on a bug report until there's some feedback on what
> the compiler should do in this situation.
> 
> With greetings and stuffies,
>  --downs

I'd also like to see this, if only for the example you gave on IRC:

with( new glTriangleStrip )
{
    glVertex(v1);
    glVertex(v2);
    glVertex(v3);
}

Which is *very* reminiscent of Python's with construct <http://www.python.org/dev/peps/pep-0343/>.  You can fake something very similar using scope statements, but Python's solution just seems that touch more elegant.

Of course, we'd probably be able to do all this if we got struct destructors... ;)

	-- Daniel "let's give the ol' horse one more flog for old times' sake..."