2

Say I have a simple PHP loop like this one

// Bad example
$array = array('apple','banana','cucumber');
for ($i = 1; $i < count($array); $i++) {
    echo $array[$i];
}

I know this is a bad practice. It's better not using count() inside a loop.

// Nice example
$array = array('apple','banana','cucumber');
$limit = count($array);
for ($i = 1; $i < $limit; $i++) {
    // do something...
}    

In Java, I would do it this way

// Bad example?
String[] array = {"apple","banana","cucumber"};
for(int i = 0; i < array.length; i++){
    System.out.println(array[i]);
}

Question: Isn't this above a bad practice too? Or it is just the same as the example below?

// Nice example?
String[] array = {"apple","banana","cucumber"};
int limit = array.length;
for(int i = 0; i < limit; i++){
    System.out.println(array[i]);
}
Simone
  • 20,302
  • 14
  • 79
  • 103
  • possible duplicate of [What is the Cost of Calling array.length](http://stackoverflow.com/questions/1208320/what-is-the-cost-of-calling-array-length) – Chris Baker Nov 28 '11 at 22:45

5 Answers5

6

Any decent compiler/interpreter should automatically optimise the first example to match the second (semantically speaking anyway, if not exactly literally), and probably the third to match the fourth. It's known as a loop invariant optimisation, where the compiler recognises that an entity (variable, expression, etc) does not vary within the loop (i.e. is invariant) and removes it to outside the loop (loosely speaking).

It's not bad practice at all anymore, if it ever was.

Mac
  • 14,615
  • 9
  • 62
  • 80
  • This isn't an answer to the question, but it is interresting. However: +1. – Martijn Courteaux Nov 28 '11 at 22:46
  • @MartijnCourteaux: Thanks for upvoting! IIRC, the question was "is this bad practice"? I specifically addressed that in my second paragraph (no, it isn't bad practice) and the rest of my answer explains why. It also explains why the third example is essentially the same as the fourth (which was the other question). – Mac Nov 28 '11 at 22:50
5

The "bad" examples you use are not equivalent, and thus are not comparable - even if they seem so on the surface. Using this description:

for (initialization; termination; increment) {
    statement(s)
}

(which is descriptive of both PHP and java loops), the initialization statement is executed once, at the start of the loop. The termination statement and the increment are executed for each iteration of the loop.

The reason it is bad practice to use PHP's count in the termination statement is that, for each iteration, the count function call occurs. In your Java example, array.length is not a function call but a reference to a public member. Therefore, the termination statements used in your examples are not equivalent behavior. We expect a function call to be more costly than a property reference.

It is bad practice to place a function call (or call a property that masks a function) in the termination statement of a for loop in any language which has the described loop mechanics. That's what makes the PHP example "bad", and it would be equally bad if you used a count-type function in Java for loop's termination statement. The real question, then, is whether Java's Array.length does indeed mask a function call - the answer to that is "no" (see the potential duplicate question, and/or check out http://leepoint.net/notes-java/data/arrays/arrays.html)

Chris Baker
  • 49,926
  • 12
  • 96
  • 115
  • Thanks Chris! In fact, my doubt was that `Array.length` could be a method - I was confusing with `String.length()`, that *is* a method. `Array.length` is just a property. So my Java "bad example" isn't really bad. – Simone Nov 28 '11 at 23:07
2

The main difference is that count() is a function whereas array.length is a property and therefore not different from a limit variable.

Niko
  • 26,516
  • 9
  • 93
  • 110
1

They are not the same, in the Java "nice example" you are not calculating the length of the array every time. Instead, you are storing that in the limit variable and using that to stop the calculation instead of the result of calling the length function on the array every iteration through the for loop.

EDIT: Both of the things that you thought were "bad practice" are bad practice and the "nice examples" are the more efficient ways (at least in theory). But it is true that in implementation there will not be any noticeable difference.

jakx
  • 748
  • 5
  • 8
1

In java this doesn't matter an array has this attribute as a constant (public final int). The difference is in java arrays have a fixed size and can not grow so there would be no need to count the elements every time to access length.

stacker
  • 68,052
  • 28
  • 140
  • 210