www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Ideas regarding flow control and loops

reply =?ISO-8859-1?Q?Marco_Aur=e9lio?= <thecoreh gmail.com> writes:
Hello! I've been following the development of the D programming language for
some time (around 1 year), and I have to say it keeps looking better.

I don't know if these have been proposed before, but I would like to make two
suggestions regarding flow control and loops:

1- if behavior on "with" statement:

On the current specification of D, if you want to check if a class can be
casted to a subclass, and do something with it, you have to do something like:

if (cast(Foo)bar)
    with(cast(Foo)bar)
    {
        DoSomething();
    }

While that works, it makes you have to write the same thing twice, and unless
some compiler optimization kicks in (not sure if compilers check for that), the
cast will have to be done twice. (and since it performs a runtime check, it
will take some time) You could also use a temporary variable, but that wouldn't
be so elegant.

My idea is to make the with statement also behave like an if statement, so the
above code could be rewritten as only:

with(cast(Foo)bar)
{
    DoSomething();
}

There's the possibility this would make existing code slower, due to
unnecessary checks for null (if you're not typecasting and are sure it's not
null), so another possibility would be making the syntax like:

if with(cast(Foo)bar)
{
    DoSomething();
}

So the default "with" behavior would be preserved. Note that since it behaves
like an if, you could add an else at the end, like:


if with(cast(Foo)bar)
{
    DoSomething();
} else {
    writeln("Not possible!");
}


2 - for .. finally, while .. finally:

This would allow having something like:

while(someCondition)
{
    DoSomething();
} finally {
    DoOtherThing();
}

The "finally" block would be called at the end of the repetition, only if no
"break" was used. This may not seem useful at first, but I think can reduce the
number of flags needed to implement various algorithms, making the code faster
and more elegant. I'm not sure if this is already possible with scope guards.

That's it.. What do you think?
Nov 03 2007
next sibling parent reply downs <default_357-line yahoo.de> writes:
Marco Aurélio wrote:
 Hello! I've been following the development of the D programming language for
some time (around 1 year), and I have to say it keeps looking better.
 
 I don't know if these have been proposed before, but I would like to make two
suggestions regarding flow control and loops:
 
 1- if behavior on "with" statement:

I used to have the same problem - I even wrote an ifIs template to get around the repetition. Then somebody clued me in to this: if (auto foo=cast(Whee) bar) { /* use foo* } ISN'T IT NEAT? <3 D.
 2 - for .. finally, while .. finally:
 
 This would allow having something like:
 
 while(someCondition)
 {
     DoSomething();
 } finally {
     DoOtherThing();
 }
 
 The "finally" block would be called at the end of the repetition, only if no
"break" was used. This may not seem useful at first, but I think can reduce the
number of flags needed to implement various algorithms, making the code faster
and more elegant. I'm not sure if this is already possible with scope guards.
 

--downs
Nov 03 2007
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
downs wrote:
 Marco Aurélio wrote:
 Hello! I've been following the development of the D programming language for
some time (around 1 year), and I have to say it keeps looking better.

 I don't know if these have been proposed before, but I would like to make two
suggestions regarding flow control and loops:

 1- if behavior on "with" statement:

I used to have the same problem - I even wrote an ifIs template to get around the repetition. Then somebody clued me in to this: if (auto foo=cast(Whee) bar) { /* use foo* } ISN'T IT NEAT? <3 D.

Oh hell yeah.
 2 - for .. finally, while .. finally:

 This would allow having something like:

 while(someCondition)
 {
     DoSomething();
 } finally {
     DoOtherThing();
 }

 The "finally" block would be called at the end of the repetition, only if no
"break" was used. This may not seem useful at first, but I think can reduce the
number of flags needed to implement various algorithms, making the code faster
and more elegant. I'm not sure if this is already possible with scope guards.

--downs

else would also be nice. foreach( foo ; bar ) DoSomethingWith(foo); finally DoSomethingAfterwards(); else DoSomethingElseSinceBarIsEmpty(); But maybe that's just me. -- Daniel
Nov 03 2007
next sibling parent reply =?ISO-8859-1?Q?Marco_Aur=e9lio?= <thecoreh gmail.com> writes:
Daniel Keep Wrote:
 else would also be nice.

This would be specially usefull for implementing collisions on 2D games with bitmap-based coldefs, something along the lines of: while(object.isCollidingWithGround()) { object.moveUp(); } finally { object.stop(); } else { object.applyGravity(); } While the object is colliding with the ground, move it up... Then stop it.. and if he wasn't colliding with the ground in the first place, apply gravity.
Nov 03 2007
next sibling parent reply downs <default_357-line yahoo.de> writes:
Marco Aurélio wrote:
 Daniel Keep Wrote:
 else would also be nice.

This would be specially usefull for implementing collisions on 2D games with bitmap-based coldefs, something along the lines of: while(object.isCollidingWithGround()) { object.moveUp(); } finally { object.stop(); } else { object.applyGravity(); } While the object is colliding with the ground, move it up... Then stop it.. and if he wasn't colliding with the ground in the first place, apply gravity.

Well, technically ... --downs PS: module test17; import std.stdio; void extwhile(lazy bool cond, void delegate() Body, void delegate() Finally, void delegate() Else) { if (!cond()) Else(); else { do Body(); while (cond()); Finally(); } } void main() { bool colliding=true; int counter=0; extwhile(colliding, { writefln("Still colliding"); counter++; if (counter==3) colliding=false; }, { writefln("Done colliding"); }, { writefln("Never collided"); } ); }
Nov 03 2007
parent reply Robert Fraser <fraserofthenight gmail.com> writes:
downs Wrote:

 PS:
 module test17;
 import std.stdio;
 
 void extwhile(lazy bool cond, void delegate() Body, void delegate()
 Finally, void delegate() Else) {
   if (!cond()) Else();
   else {
     do Body(); while (cond());
     Finally();
   }
 }
 
 void main() {
   bool colliding=true;
   int counter=0;
   extwhile(colliding,
     { writefln("Still colliding"); counter++; if (counter==3)
 colliding=false; },
     { writefln("Done colliding"); },
     { writefln("Never collided"); }
   );
 }

Heh, closures are already spreading their intoxicating power.
Nov 03 2007
next sibling parent =?ISO-8859-1?Q?Marco_Aur=e9lio?= <thecoreh gmail.com> writes:
Robert Fraser Wrote:

 downs Wrote:
 
 PS:
 module test17;
 import std.stdio;
 
 void extwhile(lazy bool cond, void delegate() Body, void delegate()
 Finally, void delegate() Else) {
   if (!cond()) Else();
   else {
     do Body(); while (cond());
     Finally();
   }
 }
 
 void main() {
   bool colliding=true;
   int counter=0;
   extwhile(colliding,
     { writefln("Still colliding"); counter++; if (counter==3)
 colliding=false; },
     { writefln("Done colliding"); },
     { writefln("Never collided"); }
   );
 }

Heh, closures are already spreading their intoxicating power.

Wow. I didn't know you could do that, even with closures.
Nov 03 2007
prev sibling parent downs <default_357-line yahoo.de> writes:
Robert Fraser wrote:
 downs Wrote:
 
 PS:
 module test17;
 import std.stdio;

 void extwhile(lazy bool cond, void delegate() Body, void delegate()
 Finally, void delegate() Else) {
   if (!cond()) Else();
   else {
     do Body(); while (cond());
     Finally();
   }
 }

 void main() {
   bool colliding=true;
   int counter=0;
   extwhile(colliding,
     { writefln("Still colliding"); counter++; if (counter==3)
 colliding=false; },
     { writefln("Done colliding"); },
     { writefln("Never collided"); }
   );
 }

Heh, closures are already spreading their intoxicating power.

It doesn't actually use closures. Completely D 1.0 :) Those { } things are short-hand for () { }, i.e. completely normal delegate literals. --downs
Nov 03 2007
prev sibling parent Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
Marco Aurélio Wrote:

 Daniel Keep Wrote:
 else would also be nice.

This would be specially usefull for implementing collisions on 2D games with bitmap-based coldefs, something along the lines of: while(object.isCollidingWithGround()) { object.moveUp(); } finally { object.stop(); } else { object.applyGravity(); } While the object is colliding with the ground, move it up... Then >stop it.. and if he wasn't colliding with the ground in the first place, >apply gravity.

What's wrong with: if (!object.isCollidingWithGround()) object.applyGravity(); else do { object.moveUp(); } while (object.isCollidingWithGround()); object.stop(); You've got one extra condition to write but its not really a big deal.
Nov 04 2007
prev sibling parent reply BCS <ao pathlink.com> writes:
Reply to Daniel,

 downs wrote:
 
 Marco Aurélio wrote:
 
 2 - for .. finally, while .. finally:
 
 This would allow having something like:
 
 while(someCondition)
 {
 DoSomething();
 } finally {
 DoOtherThing();
 }
 The "finally" block would be called at the end of the repetition,
 only if no "break" was used. This may not seem useful at first, but
 I think can reduce the number of flags needed to implement various
 algorithms, making the code faster and more elegant. I'm not sure if
 this is already possible with scope guards.
 

--downs

foreach( foo ; bar ) DoSomethingWith(foo); finally DoSomethingAfterwards(); else DoSomethingElseSinceBarIsEmpty(); But maybe that's just me. -- Daniel

I'd rather an extension of the scope syntax while(cond) { scope(last) DoOnCondFailed(); scope(break) DoOnBreak(); // or any explicet quit scope(skip) DoIfCondNeverPasses(); scope(first) goto SkipSomeStuff; ... }
Nov 03 2007
parent reply Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
BCS Wrote:

 Reply to Daniel,
 
 downs wrote:
 
 Marco Aurélio wrote:
 
 2 - for .. finally, while .. finally:
 
 This would allow having something like:
 
 while(someCondition)
 {
 DoSomething();
 } finally {
 DoOtherThing();
 }
 The "finally" block would be called at the end of the repetition,
 only if no "break" was used. This may not seem useful at first, but
 I think can reduce the number of flags needed to implement various
 algorithms, making the code faster and more elegant. I'm not sure if
 this is already possible with scope guards.
 

--downs

foreach( foo ; bar ) DoSomethingWith(foo); finally DoSomethingAfterwards(); else DoSomethingElseSinceBarIsEmpty(); But maybe that's just me. -- Daniel

I'd rather an extension of the scope syntax while(cond) { scope(last) DoOnCondFailed(); scope(break) DoOnBreak(); // or any explicet quit scope(skip) DoIfCondNeverPasses(); scope(first) goto SkipSomeStuff; ... }

Lets take these one at a time:- scope(last): - totally useless assuming I understood the meaning while(cond) { } DoOnCondFailed(); scope(skip): - saves you one conditional - not very useful if (!cond) DoIfCondNeverPasses(); else do { ... } while(cond); scope(break): - saves you a function call or two. while(cond) { ... if (cond2) DoOnBreak(); break; ... if (cond3) DoOnBreak(); break; ... } scope(first): if (cond) { DoFirstTimeOnly(); } while(cond) { ... } goto is evil so you want the opposite too scope(notonfirst): while(cond) { static bool firstTime = false; if (firstTime==false) { firstTime = true; body1(); } body2(); } For this case there is slight justification for something. but that something is a notfirst() functor. class notfirst { private: bool first; delegate doOnFirst; delegate doOnSubsequent; public: notfirst(delegate doOnFirst_, delegate doOnSubsequent_): first(true) doOnFirst(doOnFirst_), doOnSubsequent(doOnSubsequent_) {} void run() { if (first) { doOnFirst(); first = false; } else doOnSubsequent(); } }; while(cond) { doOnFirst(body1(); body2()); } What is this equivalent to in the worst case scenario that you need all four? if (!cond) DoIfCondNeverPasses(); else { DoFirstTimeOnly(); do { doOnFirst(body1(); { ... if (cond2) DoOnBreak(); break; ... if (cond3) DoOnBreak(); break; ... } } while(cond); } DoOnCondFailed(); On balance this doesn't seem like a necessary or really useful syntax improvement to me. Regards, Bruce. to me.
Nov 04 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Bruce,

 BCS Wrote:
 
 I'd rather an extension of the scope syntax
 
 while(cond)
 {
 scope(last) DoOnCondFailed();
 scope(break) DoOnBreak(); // or any explicet quit
 scope(skip) DoIfCondNeverPasses();
 scope(first) goto SkipSomeStuff;
 ...
 }

scope(last): - totally useless assuming I understood the meaning while(cond) { } DoOnCondFailed();

for(int i = 5; i>0 i--) { scope(last) ThisNeverRuns(); break; }
 scope(skip):  - saves you one conditional - not very useful
 
 if (!cond)
 DoIfCondNeverPasses();
 else do
 {
 ...
 }
 while(cond);
 

mine looks better (IMHO)
 scope(break): - saves you a function call or two.
 
 while(cond)
 {
 ...
 if (cond2) DoOnBreak(); break;
 ...
 if (cond3) DoOnBreak(); break;
 ...
 }

you prove half of my point and don't address the other half while(cond) { ... if (cond2) DoOnBreak(); break; ... // this never runs if (cond3) DoOnBreak(); break; ... } If you didn't get it correct in this case, what are the chances of making an error in a more complicated case The other part is that it is very easy to forget to add the DoOnBreak to one of the breaks (you try finding them all in old code) or adding it to every new one (Now what needs to be done on break this time). Also, it will work with mixin(string) when you can't get to the string.
 scope(first):
 
 if (cond)
 {
 DoFirstTimeOnly();
 }
 while(cond)
 {
 ...
 }
 goto is evil so you want the opposite too
 
 scope(notonfirst):
 

good idea.
 while(cond)
 {
 static bool firstTime = false;
 if (firstTime==false) { firstTime = true; body1(); }
 body2();
 }
 For this case there is slight justification for something. but that
 something is a notfirst() functor.
 
 class notfirst
 {
 private:
 bool first;
 delegate doOnFirst;
 delegate doOnSubsequent;
 public:
 notfirst(delegate doOnFirst_,
 delegate doOnSubsequent_):
 first(true)
 doOnFirst(doOnFirst_),
 doOnSubsequent(doOnSubsequent_)
 {}
 void run() {
 if (first)
 {
 doOnFirst();
 first = false;
 }
 else doOnSubsequent();
 }
 };
 while(cond)
 {
 doOnFirst(body1(); body2());
 }

My eyes!!! I can't think of anything good to say about that solution.
 What is this equivalent to in the worst case scenario that you need
 all four?
 
 if (!cond)
 DoIfCondNeverPasses();
 else
 {
 DoFirstTimeOnly();
 do
 {
 doOnFirst(body1();
 {
 ...
 if (cond2) DoOnBreak(); break;
 ...
 if (cond3) DoOnBreak(); break;
 ...
 }
 }
 while(cond);
 }
 DoOnCondFailed();
 
 On balance this doesn't seem like a necessary or really useful syntax
 improvement to me.
 

the same can be said for scope(failure/success/exit). It's all sugar. I think the scope(*) solution looks better and is easier to read an maintain in _all_ the cases you list. In all these cases the compiler can trivially implement them with copy/paste and by rearranging jumps.
 Regards,
 
 Bruce.
 to me.

Nov 04 2007
parent reply Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
BCS Wrote:

 Reply to Bruce,
 
 BCS Wrote:
 
 I'd rather an extension of the scope syntax
 
 while(cond)
 {
 scope(last) DoOnCondFailed();
 scope(break) DoOnBreak(); // or any explicet quit
 scope(skip) DoIfCondNeverPasses();
 scope(first) goto SkipSomeStuff;
 ...
 }

scope(last): - totally useless assuming I understood the meaning while(cond) { } DoOnCondFailed();

for(int i = 5; i>0 i--) { scope(last) ThisNeverRuns(); break; }

for(int i=5;i>0;i--) { ... break; } if (i<=0) ThisNeverRuns();
 scope(skip):  - saves you one conditional - not very useful
 
 if (!cond)
 DoIfCondNeverPasses();
 else do
 {
 ...
 }
 while(cond);
 

mine looks better (IMHO)

 scope(break): - saves you a function call or two.
 
 while(cond)
 {
 ...
 if (cond2) DoOnBreak(); break;
 ...
 if (cond3) DoOnBreak(); break;
 ...
 }

you prove half of my point and don't address the other half

 while(cond)
 {
 ...
 if (cond2)
   DoOnBreak();
 break;
 ...   // this never runs
 if (cond3)
   DoOnBreak();
 
 break;
 ...
 }
 
 If you didn't get it correct in this case, what are the chances of making 
 an error in a more complicated case
 

Personally I try to keep the body of a loop and in particular the control flow simple. I try to avoid breaks and put anything too large separate functions where possible.
 The other part is that it is very easy to forget to add the DoOnBreak to 
 one of the breaks (you try finding them all in old code) or adding it to 
 every new one (Now what needs to be done on break this time).
 
 Also, it will work with mixin(string) when you can't get to the string.

 scope(first):
 
 if (cond)
 {
 DoFirstTimeOnly();
 }
 while(cond)
 {
 ...
 }
 goto is evil so you want the opposite too
 
 scope(notonfirst):
 

good idea.
 while(cond)
 {
 static bool firstTime = false;
 if (firstTime==false) { firstTime = true; body1(); }
 body2();
 }
 For this case there is slight justification for something. but that
 something is a notfirst() functor.
 
 class notfirst
 {
 private:
 bool first;
 delegate doOnFirst;
 delegate doOnSubsequent;
 public:
 notfirst(delegate doOnFirst_,
 delegate doOnSubsequent_):
 first(true)
 doOnFirst(doOnFirst_),
 doOnSubsequent(doOnSubsequent_)
 {}
 void run() {
 if (first)
 {
 doOnFirst();
 first = false;
 }
 else doOnSubsequent();
 }
 };
 while(cond)
 {
 doOnFirst(body1(); body2());
 }

My eyes!!! I can't think of anything good to say about that solution.

once { foo(); } As a shorthand for: bool hasBeenRunOnce = false; if (hasBeenRunOnce == false) { hasBeenRunOnce = true; foo(); }
 What is this equivalent to in the worst case scenario that you need
 all four?
 
 if (!cond)
 DoIfCondNeverPasses();
 else
 {
 DoFirstTimeOnly();
 do
 {
 doOnFirst(body1();
 {
 ...
 if (cond2) DoOnBreak(); break;
 ...
 if (cond3) DoOnBreak(); break;
 ...
 }
 }
 while(cond);
 }
 DoOnCondFailed();
 
 On balance this doesn't seem like a necessary or really useful syntax
 improvement to me.
 

the same can be said for scope(failure/success/exit). It's all sugar. I think the scope(*) solution looks better and is easier to read an maintain in _all_ the cases you list.

 In all these cases the compiler can trivially implement them with copy/paste 
 and by rearranging jumps.
 

Regards, Bruce.
Nov 05 2007
parent BCS <BCS pathlink.com> writes:
Bruce Adams wrote:
BCS Wrote:
Reply to Bruce,
BCS Wrote:


Right. So what you really want is something that runs when the scope ends naturally but not on a break. for(int i=5;i>0;i--) { ... break; } if (i<=0) ThisNeverRuns();

that has the same behavior but duplicates the end condition check. This can be both a performance hit and can be really bad when the condition changes or if it has side effects.
 
scope(skip):  - saves you one conditional - not very useful

if (!cond)
DoIfCondNeverPasses();
else do
{
...
}
while(cond);

mine looks better (IMHO)

It doesn't justify a syntax change (IMHO)

IIRC scope is totally redundant to begin with, your counter argument apply to it's existing functionality but people still like it.
 
scope(break): - saves you a function call or two.

while(cond)
{
...
if (cond2) DoOnBreak(); break;
...
if (cond3) DoOnBreak(); break;
...
}

you prove half of my point and don't address the other half

What was the other half again?

Below
while(cond)
{
...
if (cond2)
  DoOnBreak();
break;
...   // this never runs
if (cond3)
  DoOnBreak();

break;
...
}

If you didn't get it correct in this case, what are the chances of making 
an error in a more complicated case

Harsh. I was writing at 2am or thereabouts. Also you missed a semi-colon in

 Personally I try to keep the body of a loop and in particular the control flow
simple. I try to avoid breaks and put anything too large separate functions
where possible.
 

Have you ever written real code at 2AM? I'd like to have a language that helps me not make mistakes. We're all human.
 
The other part is that it is very easy to forget to add the DoOnBreak to 
one of the breaks (you try finding them all in old code) or adding it to 
every new one (Now what needs to be done on break this time).

Also, it will work with mixin(string) when you can't get to the string.

That might be a more valid use. Care to post an example? I think we have to be careful with mixin's. They could easily be as abused as macros. There's no reason you couldn't write with a style that has an exit condition specified in the mixin. I don't like the idea of having a mixin with a break or return hidden in it (that goes beyond the scope of the mixin itself). That could make it very hard to follow the control flow.

agreed, mixin can make for some nasty code.
 
In all these cases the compiler can trivially implement them with copy/paste 
and by rearranging jumps.

I'm more worried about the programmer having to maintain code using bizarre constructs. The compiler can be clever out of sight.

It's not about the compiler being clever, it about the code having fewer internal dependencies.
 Regards,
 
 Bruce.

I like the scope solution because it states stuff where it makes a difference, not where it needs to be done. Also it states stuff in a way that make the intention of the code more clear. "do this then" rather than "when that, do this" or even worse "do this now" in several places. I'll concede it is a style issue.
Nov 05 2007
prev sibling parent =?ISO-8859-1?Q?Marco_Aur=e9lio?= <thecoreh gmail.com> writes:
downs Wrote:

 if (auto foo=cast(Whee) bar) { /* use foo* }
 
 ISN'T IT NEAT?
 <3 D.

Indeed. Even better: if (auto bar = cast(Whee) bar) { } So the variable bar of type "Whee" would hide the other variable bar at the local scope. But I still think it would be usefull to have the if+with statement.
Nov 03 2007
prev sibling next sibling parent reply Charles D Hixson <charleshixsn earthlink.net> writes:
Marco Aurélio wrote:
 Hello! I've been following the development of the D programming language for
some time (around 1 year), and I have to say it keeps looking better.
 ...
 2 - for .. finally, while .. finally:
 
 This would allow having something like:
 
 while(someCondition)
 {
     DoSomething();
 } finally {
     DoOtherThing();
 }
 
 The "finally" block would be called at the end of the repetition, only if no
"break" was used. This may not seem useful at first, but I think can reduce the
number of flags needed to implement various algorithms, making the code faster
and more elegant. I'm not sure if this is already possible with scope guards.
 
 That's it.. What do you think?

No. Finally should be the label on a block of code that will be executed *WHATEVER* happens in the preceding loop, including the raising of an exception.
Nov 03 2007
parent reply =?ISO-8859-1?Q?Marco_Aur=e9lio?= <thecoreh gmail.com> writes:
Charles D Hixson Wrote:

 No.  Finally should be the label on a block of code that will 
 be executed *WHATEVER* happens in the preceding loop, 
 including the raising of an exception.

Hmm Yeah, now that I think about it, having it on that way would make it inconsistent with the try-catch-finally behavior... Maybe adding another keyword? or something like: for(int i = 0; i < 30; i++) { if (something) break; } catch (break) { Foo(); }
Nov 03 2007
parent reply Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
Marco Aurélio Wrote:

 Charles D Hixson Wrote:
 
 No.  Finally should be the label on a block of code that will 
 be executed *WHATEVER* happens in the preceding loop, 
 including the raising of an exception.

Hmm Yeah, now that I think about it, having it on that way would make it inconsistent with the try-catch-finally behavior... Maybe adding another keyword? or something like: for(int i = 0; i < 30; i++) { if (something) break; } catch (break) { Foo(); }

That's redundant. Its the same as try { for(int i = 0; i < 30; i++) { if (something) throw breakException; } } catch (breakException) { Foo(); } Are you sure there's really a problem here? How about posting something 'evil'. If no-one in the group can think of a good refactoring then you may have a case. I suspect structured programming has been around too long to benefit much from anything new. That said, foreach was an awful long time coming so you may have a case. Regards, Bruce.
Nov 04 2007
parent reply BCS <ao pathlink.com> writes:
Reply to Bruce,

 Marco Aurélio Wrote:
 
 Charles D Hixson Wrote:
 
 No.  Finally should be the label on a block of code that will be
 executed *WHATEVER* happens in the preceding loop, including the
 raising of an exception.
 

it inconsistent with the try-catch-finally behavior... Maybe adding another keyword? or something like: for(int i = 0; i < 30; i++) { if (something) break; } catch (break) { Foo(); }

try { for(int i = 0; i < 30; i++) { if (something) throw breakException; } } catch (breakException) { Foo(); }

Tell me that is a joke. If you don't see the problems with that then.... Do you have any idea how mush potential for overhead there is in that? The other solution has one jump, that has a memory allocation (and a free at some point) a bit of stack un winding, Maybe a RTTI work and who only known what else. Plus it will (incorrectly) trigger any intervening scope(failure) and sooner or later you will need to start fabricating types to keep track of what loop the break is for.
 Are you sure there's really a problem here? How about posting
 something 'evil'. If no-one in the group can think of a good
 refactoring
 
 then you may have a case.  I suspect structured programming has been
 around too long to benefit much from anything new. That said, foreach
 was an awful long time coming so you may have a case.
 
 Regards,
 
 Bruce.
 

Nov 04 2007
parent Bruce Adams <tortoise_74 yeah.who.co.uk> writes:
BCS Wrote:

 Reply to Bruce,
 
 Marco Aurélio Wrote:
 
 Charles D Hixson Wrote:
 
 No.  Finally should be the label on a block of code that will be
 executed *WHATEVER* happens in the preceding loop, including the
 raising of an exception.
 

it inconsistent with the try-catch-finally behavior... Maybe adding another keyword? or something like: for(int i = 0; i < 30; i++) { if (something) break; } catch (break) { Foo(); }

try { for(int i = 0; i < 30; i++) { if (something) throw breakException; } } catch (breakException) { Foo(); }

Tell me that is a joke. If you don't see the problems with that then.... Do you have any idea how mush potential for overhead there is in that? The other solution has one jump, that has a memory allocation (and a free at some point) a bit of stack un winding, Maybe a RTTI work and who only known what else. Plus it will (incorrectly) trigger any intervening scope(failure) and sooner or later you will need to start fabricating types to keep track of what loop the break is for.

bool breakNow = false; for(int i = 0; i < 30 && breakNow == false; i++) { if (something) breakNow = true; ... } if (breakNow) { Foo(); } It still doesn't justify a language enhancement as far as I can see.
 Are you sure there's really a problem here? How about posting
 something 'evil'. If no-one in the group can think of a good
 refactoring
 
 then you may have a case.  I suspect structured programming has been
 around too long to benefit much from anything new. That said, foreach
 was an awful long time coming so you may have a case.
 
 Regards,
 
 Bruce.
 


Nov 05 2007
prev sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
Marco Aurélio Wrote:

 2 - for .. finally, while .. finally:
 
 This would allow having something like:
 
 while(someCondition)
 {
     DoSomething();
 } finally {
     DoOtherThing();
 }
 
 The "finally" block would be called at the end of the repetition, only if no
"break" was used. This may not seem useful at first, but I think can reduce the
number of flags needed to implement various algorithms, making the code faster
and more elegant. I'm not sure if this is already possible with scope guards.
 
 That's it.. What do you think?

Another "eh"... I just can't see its limited use justifying the added complexity.
Nov 03 2007