Ideas regarding flow control and loops
Bruce Adams
tortoise_74 at yeah.who.co.uk
Mon Nov 5 04:27:33 PST 2007
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;
> >> ...
> >> }
> > Lets take these one at a time:-
> >
> > scope(last): - totally useless assuming I understood the meaning
> >
> > while(cond) {
> > }
> > DoOnCondFailed();
>
> for(int i = 5; i>0 i--)
> {
> scope(last) ThisNeverRuns();
> break;
> }
>
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();
> > 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)
> > 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?
> 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 your for loop above does that render anything moot?
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.
>
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.
> > 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.
>
Rather than notOnFirst I think the functor is more properly called once.
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.
>
If you have too much sugar you can get diabetes. Cut down or switch to saccharin or get yourself some insulin :)
> 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.
Regards,
Bruce.
More information about the Digitalmars-d
mailing list