Re: standard vs. hand crafted loops
In article <MPG.1ed3042e2054ee4c9897ca@news.sunsite.dk>,
Jerry Coffin <jcoffin@taeus.com> wrote:
In article <postmaster-99EE9C.13283815052006
@news.west.earthlink.net>, postmaster@verizon.net says...
[ ... ]
Now, are you willing to assert that algorithms *never* reduce line
count, *never* help remove temporaries, *never* reduce cyclomatic
complexity, and *never* do a better job of communicating intent? Why or
why not?
I don't think anybody's likely to argue any of the above.
OTOH, I'd say that _many_ applications of some
algorithms, especially for_each, hurt in all these
respects on a fairly regular basis. Hurting readability
is often obvious -- how many people honestly believe that
something like:
for_each(x.begin(), x.end(),
bind1st(mem_fun(&classX::Foo), z));
is easier to read than:
for (i = x.begin(); i!=x.end(); i++)
i->Foo(z);
Nice of you to take one case, and over-generalize your example...
As far as creating more temporaries: technically 'i'
isn't a temporary,
I should have used "named variable" I guess.
but I'm going to guess it's the sort
of thing you were talking about.
I wasn't talking about the 'i' but in your case it fits. 'i' continues
to exist outside the loop and that invites silly things like attempts to
reuse it for other things, and problems with declaring 'i' later. I was
talking more about variables that end up declared outside the loop that
wouldn't have been necessary if an algorithm was used, for example:
if ( accumulate( x.begin(), x.end(), 0, &by_adding_lengths ) > 50 ) {
/* do whatever */
}
// complexity: 2, expressions: 1
as opposed to:
int temp_total = 0;
for ( vector<classX>::iterator it = x.begin(); it != x.end(); ++it ) {
temp_total += it->length();
}
if ( temp_total > 50 ) {
/* do whatever */
}
// complexity: 4 expressions: 5
BTW, which of the two above do you think is easer to read?
Which has a lower cyclometric complexity? The algorithm.
Which uses fewer named variables in this scope? The algorithm.
Which uses fewer expressions in this scope? The algorithm...
As far as cyclomatic complexity goes, the for_each
probably loses here as well. McCabe defined the
cyclomatic complexity in terms of nodes and edges in the
graph of all the control flows for the program -- and in
C++ that properly includes all the paths from throwing to
catching exceptions. Given that the loop adds only 1 to
the cyclomatic complexity, the for_each can only win if
there's no question that _none_ of what's used in its
case can possibly throw anything -- and I'm not at all
sure that's the case.
Your entire argument falls flat. The algorithm has no more chance of
throwing exceptions as the loop. The loop adds one to the complexity of
the function that contains it, the algorithm adds 0.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]