"Continue" usage

M

mdh

May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on. ( Ex
7-4 solution by Tondo and Gimpel comes to mind)
Is there a good principle/s for the good usage of "continue"...or...do
any of the regular/irregular contributors have a "favorite" way in
which it is particularly useful. Thanks as usual.
 
M

mdh

mdh said:

.....having now
seen "continue" used
Is there a good principle/s for the good usage of "continue"...or...do
any of the regular/irregular contributors have a "favorite" way in
which it is particularly useful.  

Personally, I prefer to reserve it as an indicator that an otherwise empty
loop is intended to be empty:

for(t = s; *s != '\0'; (*s != c) ? *t++ = *s++ : *s++)
{
  continue;}

*t = '\0';

Another reasonable view is that it should be used for quickly dispensing
with exceptional situations encountered in a loop where you don't want to
do any processing on this iteration (but don't want to stop the loop):

while(line_reading_function(&line, &len, fp) != EOF)
{
  skipwhite(&line);
  if(line[0] == '\0')
  {
    continue; /* empty line */
  }
  if(line[0] == '#')
  {
    continue; /* comment encountered */
  }

  /* now we can get on with processing "real" lines */
  .
 

thanks Richard for those "hooks" to hang that idea on.
 
C

CBFalconer

mdh said:
May I ask the group this somewhat non-focused question....having
now seen "continue" used in some of the solutions I have worked
on. ( Ex 7-4 solution by Tondo and Gimpel comes to mind). Is
there a good principle/s for the good usage of "continue" or do
any of the regular/irregular contributors have a "favorite" way
in which it is particularly useful. Thanks as usual.

I primarily use it to indicate an empty statement. It is not
limited to that however. For example:

while ((EOF != (ch = getc(f))) && ('\n' != ch)) continue;
 
C

Chris Dollin

mdh said:
May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on. ( Ex
7-4 solution by Tondo and Gimpel comes to mind)
Is there a good principle/s for the good usage of "continue"...or...do
any of the regular/irregular contributors have a "favorite" way in
which it is particularly useful. Thanks as usual.

I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
in a way that eliminates any need
to consider continue for that code.

To indicate an empty loop body
I find `{}` perfectly adequate
on those odd occasions
when it is needed.

Mind the gap.

[1] From my POV, natch.
 
R

Richard

Chris Dollin said:
mdh said:
May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on. ( Ex
7-4 solution by Tondo and Gimpel comes to mind)
Is there a good principle/s for the good usage of "continue"...or...do
any of the regular/irregular contributors have a "favorite" way in
which it is particularly useful. Thanks as usual.

I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
in a way that eliminates any need
to consider continue for that code.

To indicate an empty loop body
I find `{}` perfectly adequate
on those odd occasions
when it is needed.

Mind the gap.

[1] From my POV, natch.

Actually it makes perfect sense when you have your gate condition at the
top of the section - far easier to read, understand and maintain in many
cases (not all of course).

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

Now we could invert the test but then we need to scroll down to the end
of the function to be see what else happens after the block. Here we see
that nothing happens at all - we must move to the next element.

Seems clear, maintainable and decent design to me. I fail to see how it
could be construed as "bad" in any shape or form.
 
R

Richard Tobin

Richard Heathfield said:
Your example is fine, but your description is not, because you can't always
use continue to indicate an empty statement - *only* in loop contexts and
*only* where your intent is for the loop to continue from the
loop-continuation portion of the smallest enclosing iteration statement.

Unlike Fortran, where CONTINUE was a no-op, and was often used at the
end of loops because it could reliably be used to hang the line number
on.

-- Richard
 
B

Ben Bacarisse

Richard said:
I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
[1] From my POV, natch.

Actually it makes perfect sense when you have your gate condition at the
top of the section - far easier to read, understand and maintain in many
cases (not all of course).

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

Now we could invert the test but then we need to scroll down to the end
of the function

You mean "loop" presumably here.
to be see what else happens after the block. Here we see
that nothing happens at all - we must move to the next element.

There is, of course, no need to invert the test though many people
really seem to object to an empty if branch -- an empty else is fine
but an empty if seems to be OTT for most people.

It is unfortunate that your example is already negative because, to my
mind, there is slightly more clarity in:

while (n--) {
if (complexConditionMatched(n)) {
}
}

but that is just an accident of choosing a negative condition to start
with.
Seems clear, maintainable and decent design to me. I fail to see how it
could be construed as "bad" in any shape or form.

Clear and decent yes, but not 100% maintainable because you loose a
place to put code executed at the end of every loop. I honestly don't
know if this matters (I have no metric for maintainability) but people
site less complex matters are being an issue for maintainability so I
will suggest this one.

I almost never use continue but I don't think this is because I want
to write super maintainable code, just that to me the "if in a loop"
form seems to say what I mean more clearly in all the cases that have
come up.
 
R

Richard

Ben Bacarisse said:
Richard said:
Chris Dollin said:
mdh wrote:

May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on.
I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
[1] From my POV, natch.

Actually it makes perfect sense when you have your gate condition at the
top of the section - far easier to read, understand and maintain in many
cases (not all of course).

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

Now we could invert the test but then we need to scroll down to the end
of the function

You mean "loop" presumably here.

Of course. thanks.
There is, of course, no need to invert the test though many people
really seem to object to an empty if branch -- an empty else is fine
but an empty if seems to be OTT for most people.

It is unfortunate that your example is already negative because, to my
mind, there is slightly more clarity in:

while (n--) {
if (complexConditionMatched(n)) {
}
}

but that is just an accident of choosing a negative condition to start
with.

Actually it was not an accident. it was the whole point.

In your code above (and you seem to have missed my point entirely) one
most scroll down to see if an else exists and a further processing
block. With mine one doesn't. not the end of the world I know. But good
enough reasons for using continue I would have thought.
Clear and decent yes, but not 100% maintainable because you loose a
place to put code executed at the end of every loop. I honestly don't

Yes. if you need to. In this case you do not need to. It is very
clear. if you match you do something else you move to the next
element. its the whole point of my defence of "continue".
know if this matters (I have no metric for maintainability) but people
site less complex matters are being an issue for maintainability so I
will suggest this one.

I almost never use continue but I don't think this is because I want
to write super maintainable code, just that to me the "if in a loop"
form seems to say what I mean more clearly in all the cases that have
come up.

I can see nothing in my example which is not perfectly clear,
maintainable and easy to comprehend. I have demonstrated how it means
one does not have to go looking for an "else" so in fact improves
clarity.

I'm not sure I could add anything to make it much clearer as to why I
consider careful use of "continue" as a GOOD thing and not as a hastily
thrown in element in order to paint over a bad design as Chris
suggested.


--
 
B

Ben Bacarisse

Hi, my name is Eric, and I'm a `continue' abuser. I use
it as a disguised `goto', simply to avoid excessive nesting:

<fx:stands up>
Hello, my name is Ben, and *I* abuse break. Ah, it feels so good to
say it out loud!

I never get tempted by continue (see elsethread) but I can't keep my
hands off that lovely break. It is sooooo tempting, when you are all
hot and bothered, tightly bound by a strict loop invariant, just to
slip in little break and be free.

[Serious point: in some ways, break is much worse than continue
because of what happens to the way you think about your loops, but I
find myself using break much more than continue and paying the extra
thinking costs later because I do try to verify the logic of all my
loops.]
 
C

Chris Dollin

Richard said:
Chris Dollin said:
mdh said:
May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on. ( Ex
7-4 solution by Tondo and Gimpel comes to mind)
Is there a good principle/s for the good usage of "continue"...or...do
any of the regular/irregular contributors have a "favorite" way in
which it is particularly useful. Thanks as usual.

I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
in a way that eliminates any need
to consider continue for that code.

To indicate an empty loop body
I find `{}` perfectly adequate
on those odd occasions
when it is needed.

Mind the gap.

[1] From my POV, natch.

Actually it makes perfect sense when you have your gate condition at the
top of the section - far easier to read, understand and maintain in many
cases (not all of course).

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

This is exactly the kind of example that I find smelly. (Weakly
smelly, but still smelly.)

I would write the utterly obvious:

while (n--)
if (complexConditionMatched(n))
doInterestingThings(n);

(Add layout and braces and inlined function body to taste.)
Now we could invert the test but then we need to scroll down to the end
of the function to be see what else happens after the block.

No, we don't. We just look; functions are not /that/ big, especially
nowadays, and editors are not that feeble, so I'm told.
Seems clear, maintainable and decent design to me. I fail to see how it
could be construed as "bad" in any shape or form.

It's not a clear statement of intent; or, more exactly, it's not as
clear a statement as one could write with similar effort.
 
R

Richard

Richard said:
Ben Bacarisse said:
Richard said:
mdh wrote:

May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on.
I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
[1] From my POV, natch.

Actually it makes perfect sense when you have your gate condition at the
top of the section - far easier to read, understand and maintain in many
cases (not all of course).

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

Now we could invert the test but then we need to scroll down to the end
of the function

You mean "loop" presumably here.

Of course. thanks.

Actually I was too hasty to accept your correction. No. I did not mean
loop. I meant the scope of the if block.

e.g

if(match(n){
something();
}else{
somethingelse();
}

here without the continue "in your face" one must check for the else at
the end when reading the code.

This

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

something();

is much more explicit and clearer.
 
N

Nick Keighley

Hi, my name is Eric, and I'm a `continue' abuser. I use
it as a disguised `goto', simply to avoid excessive nesting:

<fx:stands up>
Hello, my name is Ben, and *I* abuse break. Ah, it feels so good to
say it out loud!

I never get tempted by continue (see elsethread) but I can't keep my
hands off that lovely break. It is sooooo tempting, when you are all
hot and bothered, tightly bound by a strict loop invariant, just to
slip in little break and be free.

[Serious point: in some ways, break is much worse than continue
because of what happens to the way you think about your loops, but I
find myself using break much more than continue and paying the extra
thinking costs later because I do try to verify the logic of all my
loops.]

I too am an inveterate break user and hardly ever use continue.
I think my continue is about the same as my goto usage.

As you say though break is potentially much worse. I think the
temptation to use it is because it it actually provides a useful
construct. continue seems to add confuscation without any particular
gain.

while (next_item() != end)
{
if (!match())
continue;

process_item();
}

seems less clear than

while (next_item() != end)
{
if (match())
process_item();
}


whilst I sometimes stuctures like this handy (and clear)

for (;;)
{
pre_process();
if (!more())
break;
post_process();
}
 
B

Ben Bacarisse

Richard said:
Actually it was not an accident. it was the whole point.

In your code above (and you seem to have missed my point entirely) one
most scroll down to see if an else exists and a further processing
block.

Don't confuse not agreeing with missing the point. I got your point
100%. I am simply, gently, disagreeing. If there is any trouble at
all to see if there is an else or anything after the if you need a
better code browser or editor. I accept is can be a problem, I prefer
not to write code by second guessing what tools people have to read it.

Yes. if you need to. In this case you do not need to. It is very
clear. if you match you do something else you move to the next
element. its the whole point of my defence of "continue".


I can see nothing in my example which is not perfectly clear,
maintainable and easy to comprehend. I have demonstrated how it means
one does not have to go looking for an "else" so in fact improves
clarity.

Can you give me an example of something simple that impacts on
maintainability? As I said, I have no measure, but people suggest
things like {} round single statements to help maintenance. If you
are in that camp (and I have no idea) then not having somewhere to put
code (for example logging) that is common to all loop cases is surely
a bigger problem.

(Personally, I consider neither to be a problem for maintenance but I
have long since given up arguing that!)
I'm not sure I could add anything to make it much clearer as to why I
consider careful use of "continue" as a GOOD thing and not as a hastily
thrown in element in order to paint over a bad design as Chris
suggested.

No, there is nothing you can add for clarity. Please don't take the
fact that you may not always able to persuade as being evidence that
your readers don't comprehend.
 
R

Richard

Chris Dollin said:
Richard said:
Chris Dollin said:
mdh wrote:

May I ask the group this somewhat non-focused question....having now
seen "continue" used in some of the solutions I have worked on. ( Ex
7-4 solution by Tondo and Gimpel comes to mind)
Is there a good principle/s for the good usage of "continue"...or...do
any of the regular/irregular contributors have a "favorite" way in
which it is particularly useful. Thanks as usual.

I have seen `continue` used sensibly [1] so rarely
that I treat any use of it
as a code smell
suggesting
that there is an opportunity
to fix the design
in a way that eliminates any need
to consider continue for that code.

To indicate an empty loop body
I find `{}` perfectly adequate
on those odd occasions
when it is needed.

Mind the gap.

[1] From my POV, natch.

Actually it makes perfect sense when you have your gate condition at the
top of the section - far easier to read, understand and maintain in many
cases (not all of course).

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

This is exactly the kind of example that I find smelly. (Weakly
smelly, but still smelly.)

Wierd. I see the above and it is 100% clear and concise. No scrolling
needed. No guesswork. In fact I can not think of anything better for
this.

I would write the utterly obvious:

while (n--)
if (complexConditionMatched(n))
doInterestingThings(n);

(Add layout and braces and inlined function body to taste.)

Of course. And the scroll down to see what, if anything, is on the else
part. Already more complicated.
No, we don't. We just look; functions are not /that/ big, especially

Immaterial. They can be. My way makes it immaterial anyway.
nowadays, and editors are not that feeble, so I'm told.

I guess you are trying to belittle my comments with that?
It's not a clear statement of intent; or, more exactly, it's not as
clear a statement as one could write with similar effort.

It is totally clear.

If I am not interested in this element then check the next one. What
could be easier. I suspect you have made your mind up so any more
discussion will be a waste of time.
 
C

Chris Dollin

Richard said:
Immaterial. They can be. My way makes it immaterial anyway.

If a function is as big as you suggest, you have already lost.
I guess you are trying to belittle my comments with that?

Your guesswork is wonky. That's not a statement about you, or
your comments, but about modern programmer's-editors.
It is totally clear.

There's an unnecessary `continue` in it that isn't contributing
to clarity. I expect constructs like `continue` that play with
control flow to pull their weight and not just substitute for
syntactic rearrangements. The power of `continue` is that it
can leap out of nested blocks and conditionals; the price of
`continue` is that you have to track down what it skips and
where it goes in a way that you don't with the "structured"
constructs. Forcing this on the reader is a load; forcing them
when a straightforward rearrangement makes it unnecessary
and IMAO adds clarity is just ... untidy.
If I am not interested in this element then check the next one. What
could be easier.

if this is interesting, process it

is easier.
I suspect you have made your mind up so any more
discussion will be a waste of time.

Of course I've made my mind up; if you want to convince me
otherwise, you need a better argument that doesn't ignore mine.
 
C

Chris Dollin

Richard said:
Once more

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/
}

Has to be easier to comprehend and check than:

while(n--){

if(complexConditionMatched(n)){
/*do processing of things we are interested in*/
}

}

There's no "has to be"; it just /isn't/ easier (for me) than
the intent-displaying code.
because in the second block one MUST go down to check the end of the
function to see what happens for the non matched element.

In your example, I can just see what happens. If you had a whole
mess of code in there, I'd do an Extract Method\\\\\\Function on
it and mutter Dark Words about whoever had written the mess.
 
B

Ben Bacarisse

Richard said:
Ben Bacarisse <[email protected]> writes:
<big snip>

I don't think there are any substantive issues there than this:
I do not. But I am a bit bewildered by your arguments here. Nothing you
have said is easier or "more maintainable" (in my mind of course) than
my example which is concise, easy to read and very, very localised
without the need to check for else statements.

Once more

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/
}

Has to be easier to comprehend and check than:

while(n--){

if(complexConditionMatched(n)){
/*do processing of things we are interested in*/
}

}

because in the second block one MUST go down to check the end of the
function to see what happens for the non matched element.

Why are you bringing up "easier to understand" -- I agreed about that
several messages ago?

The only issue I raised was maintainability. Now, I have admitted
that I don't really know what people mean here, but you brought it up
so it must mean something to you. I asked for an example of something
that, in your view impairs maintainability, but you did not offer one.
Without that I will be at a disadvantage, because I don't know what I
mean by it and you haven't said what you mean by it!

Other people seem to hold that code is more maintainable if it can be
modified by making "local changes". I posited a change: add something
that has to be done every time after the loop's (current) body. To do
that, if a loop has a continue, the maintenance programmer has to
check for that and either replace the continue with a goto or re-write
using an if that encloses the (current) body. Neither is what I
understand by a "local change".

This may not be what you mean by maintainability, in which case you
use is (by your criteria) unimpeachable, but it seems to match what I
think other people call maintainability.

Please don't repeat that your code if for cases where this change is
never warranted. If you can code for all future changes you should
write a book to tell the rest of how to do this. If, on the other
hand, you claim that this change is never need in loops that have this
specific pattern, then I'll shut up and just accept you have a much
deeper knowledge of code patterns than I have ever managed to attain
(but you should have brought up the fact that you know this never
happens when you offered the code pattern).
 
R

Richard

Chris Dollin said:
If a function is as big as you suggest, you have already lost.

Do you notice your "if" there? Why are you second guessing what the nex
block is like?
Your guesswork is wonky. That's not a statement about you, or
your comments, but about modern programmer's-editors.

I know all about modern editors. But why even bring them up. they are
immaterial to the point in hand.
There's an unnecessary `continue` in it that isn't contributing
to clarity.

Says you. I have explained why it is contributing to clarity. What YOU
exect is immateterial here since you are coming from a mindset which
already says use of continue indicates a broken design. I have given a
very simple use of it which is clear, concise and requires less code
browsing to see what happens when an element is not suitable for
processing.

Here, I will show you again:

while(n--){

if(complexConditionNotMatched(n))
continue; /* not interested. Check the next if there is one. */

/*do processing of things we are interested in*/

}

*snip*

Now it obvious to me that you have a thing against continue and no
amount of logical argument will convince you otherwise. The fact that
you are reaching for an editors functionality to make that "extra
browsing" painless is proof in the pudding to me that further
argument/discussion is pointless.

Bottom line is : you think they are bad and are used by poor programmers
to cover up poor design.

I think the above is very well designed and crystal clear.
 
R

Richard

Chris Dollin said:
There's no "has to be"; it just /isn't/ easier (for me) than
the intent-displaying code.

Because you hate continues. The reason it has to be when using metrics
like code length is simple:

its less code

its less to browse

there is no else to worry about

we jump back to start of loop while still visible when debugging.

I can not see one single negative in that code above.

Not one.
In your example, I can just see what happens. If you had a whole
mess of code in there, I'd do an Extract Method\\\\\\Function on
it and mutter Dark Words about whoever had written the mess.

I'm quite sure you would. Me? I would say "Oh that first few lines makes
it perfectly clear what elements we are interested in processing and
which not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top