Iterating over an array style question

D

Daniel Giaimo

I ran into an interesting piece of code today which I had a fairly strong
reaction to, and I was wondering if it was just me, or whether other
people feel the same way about it. I don't really want to bias the
sample by saying whether I liked the code or not, so I'll just ask, how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}

--
Dan Giaimo
 
A

Arne Vajhøj

I ran into an interesting piece of code today which I had a fairly strong
reaction to, and I was wondering if it was just me, or whether other
people feel the same way about it. I don't really want to bias the
sample by saying whether I liked the code or not, so I'll just ask, how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}


I don't like it.

But then it is one of the few ways Java can compete
with:
http://en.wikipedia.org/wiki/Brainfuck
etc.

Arne
 
E

Eric Sosman

I ran into an interesting piece of code today which I had a fairly strong
reaction to, and I was wondering if it was just me, or whether other
people feel the same way about it. I don't really want to bias the
sample by saying whether I liked the code or not, so I'll just ask, how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}


I use the "reverse loop" myself sometimes, but I prefer to
write `--i >= 0'. No difference; it just seems to me to read
more smoothly.

If I were to use a post-decrement (in C, say, with an `unsigned'
integer), I'd write `i-- > 0'. Whitespacecanbebeneficial.
 
A

Alex Mentis

Eric said:
I ran into an interesting piece of code today which I had a fairly
strong reaction to, and I was wondering if it was just me, or
whether other people feel the same way about it. I don't really
want to bias the sample by saying whether I liked the code or not,
so I'll just ask, how do you feel about the following code for
iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}


I use the "reverse loop" myself sometimes, but I prefer to
write `--i >= 0'. No difference; it just seems to me to read
more smoothly.

If I were to use a post-decrement (in C, say, with an `unsigned'
integer), I'd write `i-- > 0'. Whitespacecanbebeneficial.


Personally, I don't like either of the "clever" versions. When
compared to the more traditional version:

for (int i = arr.length; i >= 0; i--) ...

they save between one and three non-whitespace characters of typing
(depending on prefix or postfix decrement) in exchange for introducing
more complexity in thinking about the terminating condtion, which
varies depending upon subtle differences between the operation of
prefix and postfix decrement.

Having said that, between the two non-traditional versions, I prefer
the "--i >= 0" version, which makes it clear that i is being
decremented, then tested to be in the range of arr's indices. "i-->0"
has an interesting arrow effect that kind of looks like "i is moving
toward 0", but it hides the test-then-decrement behavior that is
actually happening.

Alex
 
A

Alex Mentis

Patricia said:
Alex said:
Eric said:
On 11/23/2010 8:01 PM, Daniel Giaimo wrote:
I ran into an interesting piece of code today which I had a
fairly strong reaction to, and I was wondering if it was just
me, or whether other people feel the same way about it. I
don't really want to bias the sample by saying whether I liked
the code or not, so I'll just ask, how do you feel about the
following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}
I use the "reverse loop" myself sometimes, but I prefer to
write `--i >= 0'. No difference; it just seems to me to read
more smoothly.

If I were to use a post-decrement (in C, say, with an `unsigned'
integer), I'd write `i-- > 0'. Whitespacecanbebeneficial.


Personally, I don't like either of the "clever" versions. When
compared to the more traditional version:

for (int i = arr.length; i >= 0; i--) ...


I agree in general, but think you need to start at arr.length-1.
Indeed, one of the merits of this form is that the initial value of i
is the index of the first array element to be processed.

Patricia


Yes, you are right, i starts at (arr.length - 1), thanks (it's still
early in the morning here).

So I need to edit my previous character calculations: OP's version
saves five characters, I think, and the alternate non-traditonal
version saves three. Still not worth it to me.
 
A

Alex Mentis

Leif said:
Daniel Giaimo said:
how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}



I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


There's also a school of thought that generally believes that Boolean
tests shouldn't have side-effects.
 
E

Eric Sosman

Daniel Giaimo said:
how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}



I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


Chacun à son goût, but I can't generate much enthusiasm for
this rule. One of its consequences is that `++' and `--' cannot
be used in any context where the value of the (sub-)expression
is used: You could do `--i;' but not `x = a[--i];', for example.
 
J

Joshua Cranmer

If I were to use a post-decrement (in C, say, with an `unsigned'
integer), I'd write `i-- > 0'. Whitespacecanbebeneficial.

What, you never heard about the famous `down to' operator in C? It's the
--> operator: i --> 0! :)
 
J

Joshua Cranmer

I ran into an interesting piece of code today which I had a fairly strong
reaction to, and I was wondering if it was just me, or whether other
people feel the same way about it. I don't really want to bias the
sample by saying whether I liked the code or not, so I'll just ask, how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}


I'm not a fan of this for the following reasons:

1. It takes me a few seconds to realize whether or not this is correct.
Following the maxim from a programming class, "If you have to make your
grader (reader) think about whether or not it's correct, that is not a
good sign."

2. Reflexively, I always point out that a reverse array iteration starts
at length - 1, not length. That's handled by the condition, but it's not
immediately obvious. In a similar vein, it's not immediately obvious
that you are accessing the first element.

3. I don't really like for loops that lack the increment step, or the
condition step for that matter. It may pollute the scope of the index
variable, but you can easily reuse that if you have to, so it's not a
big deal to me.
 
E

Eric Sosman

Leif said:
Daniel Giaimo said:
how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}



I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


There's also a school of thought that generally believes that Boolean
tests shouldn't have side-effects.


Who are the teachers in these "schools," and why haven't they
been fired yet?

BufferedReader rdr = ...;
for (String line; (line = rdr.readLine()) != null; ) // BZZZT!

Pattern patt = ...;
Matcher match = patt.matcher(...);
if (match.matches()) // BZZZT!

.... and so on, and so on. Sounds like a silly school.
 
T

Tom McGlynn

     Chacun à son goût, but I can't generate much enthusiasm for
this rule.  One of its consequences is that `++' and `--' cannot
be used in any context where the value of the (sub-)expression
is used: You could do `--i;' but not `x = a[--i];', for example.

My own -- admittedly idiosyncratic -- preference is to forego use of
the increment and decrement operators precisely because they tend to
lead one to writing statements with side effects like
x = a[--i];
For me at least this tends to buggy code when I need to modify this
line to
x = weight*a[--i]; (sic)

So I just use
i -= 1;
x = a;

and keep my life simple and my code clearer.

Regards,
Tom McGlynn
 
J

Joshua Cranmer

I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.

Chacun à son goût, but I can't generate much enthusiasm for
this rule. One of its consequences is that `++' and `--' cannot
be used in any context where the value of the (sub-)expression
is used: You could do `--i;' but not `x = a[--i];', for example.

Whether or not to use postfix/prefix expressions, for me at least,
depends on what I'm doing.

If I'm accessing an array, I prefer to do the increment/decrement before
access instead of using prefix (i.e., i--; x = a;). However, I don't
have an issue with postincrement/decrement (most useful when doing I/O:
number = (arr[i++] & 0xff) << 8 | (arr[i++] & 0xff);). On the other
hand, I prefer it reversed for conditions: --i >= 0 instead of i-- > 0.
 
A

Alex Mentis

Eric said:
Leif said:
how
do you feel about the following code for iterating over an
array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}


I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


There's also a school of thought that generally believes that
Boolean tests shouldn't have side-effects.


Who are the teachers in these "schools," and why haven't they
been fired yet?

BufferedReader rdr = ...;
for (String line; (line = rdr.readLine()) != null; ) // BZZZT!

Pattern patt = ...;
Matcher match = patt.matcher(...);
if (match.matches()) // BZZZT!

... and so on, and so on. Sounds like a silly school.


I said "generally believes". It's not a law, it's a rule. Rules are
made to be broken, but one should 1) know the rule being broken and 2)
have a good reason to do so. Achieving the reverse loop, imo, is not a
compelling reason to break the rule.
 
A

Alex Mentis

Eric said:
BufferedReader rdr = ...;
for (String line; (line = rdr.readLine()) != null; ) // BZZZT!

Pattern patt = ...;
Matcher match = patt.matcher(...);
if (match.matches()) // BZZZT!

... and so on, and so on. Sounds like a silly school.

As for your code above, why not use:

BufferedReader rdr = ...;

String line = rdr.readLine();
while (line != null)
{
line = rdr.readLine();
}

That seems much clearer to me.

Your second example doesn't appear to have a side-effect, so I'm not
sure what your point is there. match.matches() simply returns a
Boolean, which is what is expected in the condition part of the if
statement. It's not checking a condition and also changing some
variable before or after it's done.
 
A

Arne Vajhøj

Daniel Giaimo said:
how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}



I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


Then there would not be a need for the two versions.

Arne
 
A

Arne Vajhøj

Leif said:
how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}


I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


There's also a school of thought that generally believes that Boolean
tests shouldn't have side-effects.


Who are the teachers in these "schools," and why haven't they
been fired yet?

BufferedReader rdr = ...;
for (String line; (line = rdr.readLine()) != null; ) // BZZZT!


That is not very nice code either.

BufferedReader rdr = ...;
String line;
while((line = rdr.readLine()) != null)

is what I will consider the idiomatic solution.
Pattern patt = ...;
Matcher match = patt.matcher(...);
if (match.matches()) // BZZZT!

That construct is very common.

JDBC ResultSet is similar.
... and so on, and so on. Sounds like a silly school.

As it often is, then it is a matter of balance.

No side effect is better than side effect.

No temporary variable is better than temporary variable (in this
case - can not be generalized).

It is a choice.

Arne
 
A

Alex Mentis

Arne said:
Daniel Giaimo said:
how
do you feel about the following code for iterating over an array?

int[] arr = {1, 2, 3, 4}

for(int i=arr.length; i-->0;)
{
System.out.println(arr);
}



I don't like it. Somewhere, I picked up a rule about how good code
shouldn't rely on the difference between the post-increment and
pre-increment operators.


Then there would not be a need for the two versions.

Arne


Technically there's not really a "need" for either. They're just
syntactic sugar. There are languages that get along fine without
increment and decrement operators at all.
 
A

Arne Vajhøj

As for your code above, why not use:

BufferedReader rdr = ...;

String line = rdr.readLine();
while (line != null)
{
line = rdr.readLine();
}

That seems much clearer to me.

Two identical calls are not so nice.
Your second example doesn't appear to have a side-effect, so I'm not
sure what your point is there. match.matches() simply returns a
Boolean, which is what is expected in the condition part of the if
statement. It's not checking a condition and also changing some
variable before or after it's done.

Hm.

I checked the docs.

It seems as if you are correct.

But find instead of matches has the side effect. Eric
probably got those two mixed up.

Arne
 
L

Lew

     Chacun à son goût, but I can't generate much enthusiasm for
this rule.  One of its consequences is that `++' and `--' cannot
be used in any context where the value of the (sub-)expression
is used: You could do `--i;' but not `x = a[--i];', for example.

My own -- admittedly idiosyncratic -- preference is to forego use of
the increment and decrement operators precisely because they tend to
lead one to writing statements with side effects like
   x = a[--i];
For me at least this tends to buggy code when I need to modify this
line to
   x = weight*a[--i]; (sic)

So I just use
   i -= 1;
   x  = a;

and keep my life simple and my code clearer.


There's nothing unclear about the code you marked with "(sic) [sic]".

Unless you don't know Java.

JLS §15.7
 
A

Alex Mentis

Arne said:
Two identical calls are not so nice.

I don't believe that aesthetics and readability are always equivalent.
While two identical calls might not "look nice," it communicates quite
clearly what is actually intended by the programmer and doesn't
actually make any difference in how the JVM is going to execute the
algorithm.

In any case, a while loop is better for this application than a for
loop, so I appreciate your previously-posted "idiomatic solution".
While it does have a side-effect, I think that is a better example for
when it is appropriate to break the "rule" than others that have been
posted.
 

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

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,129
Latest member
FastBurnketo
Top