Re: The case for (or against) 'continue'
On Feb 19, 3:21 am, Jerry Coffin <jcof...@taeus.com> wrote:
In article <gnfn6m$h7...@news.motzarella.org>, al...@start.no says...
[...]
At the same time, I don't think it's a particularly strong argument
against continue in general. Just for example, in processing a list of
files (following the Unix-based convention that names starting with '.'
are hidden), I've written loops like this:
while (there's another file) {
if (filename[0] == '.')
continue; // ignore hidden file
process file
}
IMO, this is quite reasonable and understandable.
Not really. You've introduced an invariant in a way which
doesn't make it clear that it is present. I'd write:
while ( there's another file ) {
// invariant introduced by the while: there is a file
if ( filename[ 0 ] != '.' ) {
// invariant introduced by the if: the filename
// doesn't start with '.'
}
}
Done this way, the nesting makes the scope of each invariant
very clear. Written using the continue, it's not at all clear
that the if actually establishes an invariant for the code which
follows.
And of course, if the code in the if (in my case) is more than
two or three lines, it really belongs broken out in another
function.
(There's another very elegant solution, of course---to arrange
for your iterator over the filenames to filter out the filenames
you don't want. But that's would make the discussion irrelevant
to the issue here.)
For the job above, I'd
probably do things a bit differently (than anybody else on earth),
something like this:
// warning: untested code.
namespace {
enum returns {FIRST, SECOND, EQUAL};
template <class T>
int lesser(T const &a, T const &b) {
if (a<b)
return FIRST;
if (b<a)
return SECOND;
return EQUAL;
That would be:
return a < b
? FIRST
: b < a
? SECOND
: EQUAL ;
of course. This is one case where the ?: operator definitely
makes the code a lot more readable. (It's clear at a glance
that the function really is a function, in the purest sense of
the word.)
}
}
template <class inputIter>
bool disjoint(inputIter first1, inputIter last1,
inputIter first2, inputIter last2) {
inputIter iters[2] = {first1, first2};
returns ret;
while (EQUAL != (ret=lesser(*first1, *first2))
&& iters[0] != last1
&& iters[1] != last2)
{
++iters[ret];
}
return ret!=EQUAL;
}
The more I program, the more my code comes full circle to
resemble ancient Fortran -- flow control based only on +, 0 or
-, and everything else is subscripting! :-)
It depends on the domain, but there are more than a few cases
where a three way if would be nice. Your lesser template,
combined with a switch, could do the trick.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34