This is a performance JavaIdiom. (But we also seem to be talking about loops in C and C++ and Smalltalk and Lisp). The common way of coding an for statement is as follows: for (int i=0;i<''upperbound'';i++) { ... do something } (Even the second example that is concerned with performance in CheckDontCatch uses this idiom). When you know ''upperbound'' is invariant, sometimes a different idiom can speed this loop up a little. * calculate ''upperbound'' once Sometimes you might measure to see if it would be faster to * count down When you know ''upperbound'' changes (is not invariant), perhaps it would be less confusing to use ''while'' instead of ''for''. ---- '''calculate ''upperbound'' once''' In the vast majority of cases, ''upperbound'' is an invariant value obtained though some function call such as array.length, string.length() or arraylist.size(). Most compilers are so dumb that they call that function on every iteration, just in case it has changed. ''Don't know about Java, but C/C++ compilers are '''prohibited''' (in general) from optimizing out such function calls; as there is no way for the compiler to know whether or not the function has SideEffect''''''s or depends on external state (and might return different values on successive calls).'' [in the case of java strings and arrays, strings are immutable, and arrays are fixed-size, so the compiler can confidently hoist the upperbound calculation out of the loop (the same holds for strings and arrays in .net languages, too, although in c# I'd just use a foreach, since the compiler will produce IL exactly equivalent to the for loop)] Most of the time,the programmer knows it is an invariant. (Sometimes a SufficientlySmartCompiler will also figure this out). When ''upperbound'' really is invariant, the following syntax causes the invariant ''upperbound'' value to be calculated once. for(int i=0,iMax=''upperbound'';i #include #include int sumArray(const std::vector &vec) { int sum = 0; for (int i = 0; i < vec.size(); i++) sum += vec[i]; return sum; } int sumArrayEfficiently(const std::vector &vec) { int sum = 0; int upperBound = vec.size(); for (int i = 0; i < upperBound; i++) sum += vec[i]; return sum; } int sumArrayWithIterator(const std::vector &vec) { int sum = 0; for (std::vector::const_iterator i = vec.begin(); i != vec.end(); ++i) sum += *i; return sum; } int sumArrayCountDown(const std::vector &vec) { int sum = 0; for (int i = vec.size(); i--; ) sum += vec[i]; return sum; } int sumArrayCountDown2(const std::vector &vec) { int sum = 0; for (int i = vec.size(); i-->0; ) sum += vec[i]; return sum; } const int iterations = 100000; int main(int argc, char *argv[]) { std::string flag = argv[1]; std::vector vec(100); for (int i = 0; i < vec.size(); i++) vec[i] = rand(); if (flag == "-1") for (int i = 0; i < iterations; i++) sumArray(vec); if (flag == "-2") for (int i = 0; i < iterations; i++) sumArrayEfficiently(vec); if (flag == "-3") for (int i = 0; i < iterations; i++) sumArrayWithIterator(vec); if (flag == "-4") for (int i = 0; i < iterations; i++) sumArrayCountDown(vec); if (flag == "-5") for (int i = 0; i < iterations; i++) sumArrayCountDown2(vec); } Timing results with GCC 2.95.2, compiled with -O2: time ./test -1 # sumArray real 0m0.082s user 0m0.080s sys 0m0.000s time ./test -2 # sumArrayEfficiently real 0m0.066s user 0m0.070s sys 0m0.000s time ./test -3 # sumArrayWithIterator real 0m0.066s user 0m0.060s sys 0m0.000s time ./test -4 # sumArrayCountDown [Not yet tested] time ./test -5 # sumArrayCountDown [Not yet tested] ---- "pretty" code "i-->0" from CatchDontCheckRefuted added to the above test as "sumArrayCountDown2()". Do we really need to drag C obfuscation into this discussion? Why would anyone want to strip the whitespace out of what was a clear expression in order to simulate a non-existent syntax? A writer should not make code unclear to future readers just because the writer thinks it looks cool. ---- Care to test also this? Surely it expresses the programmer�s intention (to have a sum of all the elements of the array) most clearly. (Of course, inside it should look very much like sumArrayWithIterator� though this one evaluates end() OnceAndOnlyOnce.) inline int sumArrayWithAlgorithm(const std::vector& vec) { return std::accumulate(vec.begin(), vec.end(), 0); } Also, this test will not show much difference between indexes and iterators, because for std::vector iterators are usually pointers; but this one will be a completely different story: int sumListWithIndex(const std::list& list) { int sum = 0; for (size_t i = 0; i < list.size(); ++i) { sum += list[i]; // Warning! [] has linear time complexity } return sum; } int sumListWithIterator(const std::list& list) { int sum = 0; for (std::list::const_iterator i = list.begin(), e = list.end(); i != e; ++i) { sum += *i; } return sum; } // almost equivalent to sumListWithIterator internally // but uses sum = sum + *i int sumListWithAlgorithm(const std::list& list) { return std::accumulate(list.begin(), list.end(), 0); } // should be exactly equivalent to sumListWithIterator // not sure about the syntax, though� int sumListWithBoostLambda(const std::list& list) { using boost::lambda::_1; int sum = 0; std::for_each(list.begin(), list.end(), sum += _1); return sum; } ---- I really dig the way BASIC does it (minus goofy block ending conventions): for x = 3 to 50 step 2 {....} Or for x = 3 to 50 step 2 .... endfor It is easy to remember and English-like. I am not normally a fan of English-like syntax, but the for-loop is an exception. (Step 1 is the default of no step clause). Note ColdFusionLanguage: ... ---- I like that Basic layout too - but there is something which annoys me about loops in general. More often than not, there is a need to exit at other than the beginning or the end of the loop. This is a common requirement across all languages. Yet the syntactic structures we use all hide the exit condition within the body of the loop, not at the same level as the loop. Like - for x = 3 to 50 step 2 .... If Not(Condition) leave .... If (Condition) leave .... endfor I am used to, and prefer, this sort of syntax - for x = 3 to 50 step 2 Code .... .... Until Condition Code .... .... While Condition Code .... .... endfor or, using RubyLanguage style for the exits, for x = 3 to 50 step 2 Code .... .... Leave If Condition Code .... .... Leave Unless Condition Code .... .... endfor The main reason I prefer this is that it gives a clearer visual scan of the code. It makes loops and their exit conditions clearer. -- PeterLynch ''In BASIC, a "for" usually has a matching "next", not an "endfor".'' 100 for x = 1 to 10 110 print x 120 next x It's kind of reworked BASIC based on TheRightWayToDoWordyBlocks. ---- I read something about optimization once that said to iterate over an array on a Pentium, it was (at least in certain situations - I forget which) more efficient to do this (for clarity, I'm decompiling assembly here): element *end = array+n; int i = -n; do { /* Do stuff with end[i] */ } while (++i); I think if n might be zero it's better to test it outside of all that, and avoid the initialization. ---- See UseEnumerationsInsteadOfForLoops, RefactorMatchLoopToUsage ---- CategoryOptimization, CategoryLanguageFeature, CategoryIdiom, CategoryLoops