Iterating over an array style question

S

Stefan Ram

Tom Anderson said:
Statements in imperative languages don't have side-effects; they have
effects. That's what they're for.

Hey, don't steal my opinions! This is already my opinion!¹

Well, after all, statements in imperative languages
might have »side-effects« if we agree to use this
term for any effects not specified in the documentation.

For example, the execution of the following statement
has two effects:

++i;

1st It increments i.

2nd It heats my room (via the microprocessor, which
gets heated by the execution).

However, »2nd« is not a specified effect, so it might be
called »side-effect«. (Writing data to a memory of n bits
at Temperature T will at least create the heat k ln(2) T,
where k is Boltzmann's constant.)

¹) For example, in this post, I prefer »effect« to
»side-effect« in 2004:

|Message-ID: <[email protected]>
|(...)
| To me, "imperatively" means effect[1]-based and "functionally"
|(...)
| [1] aka "side-effect", i.e., a change of state happening

Here, I express this opinion in German in 2006:

|Message-ID: <[email protected]>
|(...)
|Ich bin der Meinung, daß das, was man "side-effect" nennt,
|am besten "Wirkung" genannt werden sollte

(»It is my opinion, that, what is called "side-effect", should
better be called "effect")
 
D

Daniel Giaimo

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);
}


The code seems to be syntactically correct, but lacks a specification
of its intended behavior, so, semantically, I cannot make assertions
about it.


I agree. My main concern with it was the amount of thought it would take
the average programmer to come to that conclusion when glancing over code
written like that. I certainly misparsed it the first time I read it,
thinking it would throw an Exception at first glance, and needed to think
more carefully about it before coming to the conclusion that it was
correct. I showed it to a very successful, 40-year veteran of the
industry, highly recommended by many of his current and former coworkers,
considered a "wizard" by quite a few of them, who has programmed in more
languages than I can name, and he misparsed it on his first reading
thinking it wouldn't output the 0th element of the array, before thinking
more carefully and coming to the conclusion that it would work.

I feel quite strongly that when you write code you should aim for it to
be readable and understandable as quickly as possible by the majority of
engineers who may run across it. That means using common idioms where
appropriate, and clearly documenting uncommon ones. I feel this example
quite definitely falls in the "uncommon idiom" bucket, if it is even used
by enough people to be called an "idiom" at all.
I would have written the loop as

for( int i = arr.length - 1; i >= 0; --i ) java.lang.System.out.println(
arr[ i ]);

, which is my »canonical« wording for a loop that counts downwards in
a numerical range.

That's what I would do too. And frankly, I don't understand why the
person who expressed his preference for the above code doesn't use this
form. Especially given his argument in favor of his code. His argument
essentially boiled down to the fact that when the compiler has to convert
a comparison to machine code, then it has to do a subtract and then a
compare to 0 so it is more efficient to do a compare to 0 than a compare
to any other number. I didn't argue with him, since, as I've expressed
elsewhere in this thread, I don't enjoy arguing with idiots, so I avoid
it when I can, but it seems to me that there are numerous problems with
this argument:

a) This is an argument in favor of counting down an array when possible
instead of up it. It is not an argument in favor of putting a decrement
operator in the test clause of a for statement, which was my main problem
with the code as written and the reason I misparsed it in the first place.

b) This argument assumes that the architecture you are compiling on
implements integer comparison by subtract and compare to zero. While
this may be true for the vast majority of processors out there currently,
there is no guarantee that it is true for all of them, and there is
certainly no guarantee that it will be true for all architectures that
you want to support in the future.

c) This argument assumes that the Java compiler is compiling the code the
way you think it is compiling the code. This is an unwarranted
assumption even in a language like C where you are much closer to the
machine than you are in Java and which compiles down directly to machine
code. It is completely unjustifiable as an assumption when you are
working in a language that does not even get compiled to machine code.

d) This kind of thinking is a classic case of "premature optimization".
There is no excuse for using an uncommon idiom for performance reasons
unless profiling has shown the need to change to that idiom. There is
certainly no excuse to leave such a change undocumented.
You might ask the author about the code or suggest improvements, but
do this in a kind and calm way! The way such issues are communicated
among team members might be more important for the project success
than issues of microstyle of source code.

Absolutely. And if I actually had to work with this person, I would try
to be nice about it. Thankfully, though, I don't have to work with them,
and will be trying to keep it that way for the foreseeable future.

--
Dan Giaimo
 
E

Eric Sosman

[... concerning `weight*a[--i]' ...]
Java programmers should be expected to know the language if they're
being paid to know the language. [...]


On occasion, Lew, you have scolded people for ignoring naming
and formatting conventions, the reason (sometimes stated, sometimes
implied) being that sticking with familiar conventions improves
readability. That is, you see value in following patterns beyond
those that the language itself enforces. I put it to you that

package FEDEX;import java.math.BigInteger;public class clown
{public static void main(String[]BigIntiger){System.out.
println(new String(new clown("Champagne Charlie"));}private
String JFrame;public clown(String Pattern){clown IOException
=this;IOException.JFrame=new String(Pattern);}public String
tostring(){return JFrame+" is my name!";}}

.... is perfectly legal Java, which "Java programmers should be expected
to know." Are we agreed?

However, I don't think you'd argue that a Java programmer should
be expected to *accept* such rot.
 
D

David

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);
}


That's genius, but i would immediately fire anyone who wrote it.

tom


I'm of the same mind. I don't really care if code looks elegant.
If I'm tracking a bug and I need to track through swathes of code this
is exactly the sort of thing I'd miss on the first pass.
I tend to avoid pre and post fix notation like this simply because you
have to pause and think about what's happening in the detail. When you
track problems and really need to follow the higher level logic this
is either missed or a distraction.

While the maxim "don't repeat yourself" is valid, so is "keep it
clear". Keep your *intention* clear and unmistakable. Don't give the
poor sap that follows you any more grief than is necessary.
 
T

Tom Anderson

Hey, don't steal my opinions! This is already my opinion!?

Too late!
Well, after all, statements in imperative languages
might have ?side-effects? if we agree to use this
term for any effects not specified in the documentation.

Alright. Although i usually use the term 'bug' for those.
For example, the execution of the following statement
has two effects:

++i;

1st It increments i.

2nd It heats my room (via the microprocessor, which
gets heated by the execution).

However, ?2nd? is not a specified effect, so it might be
called ?side-effect?. (Writing data to a memory of n bits
at Temperature T will at least create the heat k ln(2) T,
where k is Boltzmann's constant.)

Definitely a bug.

AIUI and OT, what creates the heat is *destroying* bits - in this case,
the values that were in the memory before it was written to. A crafty plan
my colleagues and i came up with over dinner the other evening was to
arrange microprocessors and memory to decouple the changing and
destruction of bits; in the case of memory, this would involve a second
cable coming out of the back of the DIMM, carrying the bits displaced from
the memory by fresh writes, and leading to some sort of random bit bucket.
The bit bucket could just destroy the discarded bits; this would produce
heat, but would at least do it somewhere remote from the actual work,
which could be more easily cooled. A development of this idea would be to
export the bits via the network interface, then ship them over the
internet to cold places, where they could be destroyed for heating. An
alternative would be that the bits would not be destroyed, but mixed about
a bit and then recycled as high-quality random bits. As the use of
cryptography becomes more widepsread, the demand for random bits is
increasing, so this could simultaneously meet this need and dispose of
unwanted boolean values without accelerating the heat death of the
universe.
Here, I express this opinion in German in 2006:

|Message-ID: <[email protected]>
|(...)
|Ich bin der Meinung, da? das, was man "side-effect" nennt,
|am besten "Wirkung" genannt werden sollte

(?It is my opinion, that, what is called "side-effect", should
better be called "effect")

So is there no German for 'side-effect', or no English for 'Wirkung'?

tom
 
S

Stefan Ram

Tom Anderson said:
AIUI and OT, what creates the heat is *destroying* bits - in this case,
the values that were in the memory before it was written to.

Yes, that's why I took care to find a statement
with a write operation, not a mere »calculation«.

A write operation usually involves deleting the
previous state.
a second cable coming out of the back of the DIMM, carrying
the bits displaced from the memory by fresh writes

Something similar is know by the name of:

http://en.wikipedia.org/wiki/Fredkin_gate

. An adder can be constructed with a Fredkin gate,
but a destructive write operation cannot.
So is there no German for 'side-effect', or no English for 'Wirkung'?

English »side-effect« ~ German »Nebenwirkung«,
English »effect« ~ German »Wirkung«

But some Germans still prefer to use English phrases
in German sentences, for example,

- when they have read them in an English text and are
not sure how to translate them or are too lazy to
think of a translation or to look up a translation or

- because English phrases are more prestigious to them
or because

- they heard others use these English phrases in this
way or they read them in German advertisments (which
often contain some English words) or because

- some English phrases, when used in German, carry less
possible meanings (are more specific) than the German
translation.

Often, wrong "sounds-like" translations are used:

English Correct Translation Wrong Sounds-like Translation

Side-Effect Nebenwirkung Seiteneffekt, Seiten Effekt
Instance Exemplar Instanz
.... ... ...
 
S

Stefan Ram

But some Germans still prefer to use English phrases
in German sentences, for example,

Or, - sometimes - when there really is no German
translation. For example, I do not know good
translations for »upcast«, »downcast«, or »web browser«.
 
L

Lew

[... concerning `weight*a[--i]' ...]
Java programmers should be expected to know the language if they're
being paid to know the language. [...]


On occasion, Lew, you have scolded people for ignoring naming
and formatting conventions, the reason (sometimes stated, sometimes
implied) being that sticking with familiar conventions improves
readability. That is, you see value in following patterns beyond
those that the language itself enforces. I put it to you that

package FEDEX;import java.math.BigInteger;public class clown
{public static void main(String[]BigIntiger){System.out.
println(new String(new clown("Champagne Charlie"));}private
String JFrame;public clown(String Pattern){clown IOException
=this;IOException.JFrame=new String(Pattern);}public String
tostring(){return JFrame+" is my name!";}}

... is perfectly legal Java, which "Java programmers should be expected
to know." Are we agreed?

However, I don't think you'd argue that a Java programmer should


Good point, Eric.

Again, I am not saying that the style in question is good, only that it is not
unclear. The obfuscation caused by eliminating whitespace was not at issue in
the idiom under question, so there's a bit of apples and oranges comparison in
your example. What was at issue, or at least what I was addressing, was
whether the semantics of a particular idiom
x = weight*a[--i]; (sic)


were clear. Once again, as I stated upthread, "clear" and "desirable" are not
perfect synonyms. I will graciously grant that the idiom could be unclear to
careless reading or careless readers, neither of which have any business in
code maintenance, and that it might cost two or three seconds in extra
ratiocination by the poor, poor hapless maintenance programmer. As a matter
of polish and style, and assistance to debugger step-throughs, it does make
sense to recast this expression as
{
final int j = i--;
x = weight [j] * a ;
}


But now we can argue aimlessly and endlessly that the code is too "verbose",
the argument proffered by people who aren't busy calling one names for finding
legal Java semantically unambiguous.

What astounds me is the frenzy to which some people are driven by the
suggestion that a programmer should have minimal skills in their profession.
Why is that such a horrid, heretical thing to suggest? There seems to be a
body of apologists that programming should be made easy for people unfamiliar
with the programming language, that it should not require even elementary,
introductory knowledge.

I am bemused.
 
A

Arne Vajhøj

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.

The two identical calls are certainly very readable.

I am more concerned about the update situation, where the
maintainer has to remember to change both.
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.

There is probably a reason why it is so common.

:)

Arne
 
A

Arne Vajhøj

Wed, 24 Nov 2010 14:49:17 -0500, /Arne Vajhøj/:

Matcher.matches() has the side effect of changing the Matcher's state
pretty much like Matcher.find() - see

True.

That most likely is state. It would extremely inefficient if it were
not state.

Arne
 
A

Arne Vajhøj

Arne wrote "Two identical calls are not so nice."

I agree with Arne. There is a maintenance issue involved with remembering
to change both if you change one. While I admit to having done the same
thing a time or two, I am never comfortable in doing it.

Arne's code eliminates the duplicate call, but still has the scope issue.
I vote for the for-loop idiom.

The scope problem rarely has any practical impact.

And the problem seems a a natural "while problem".

Arne
 
A

Arne Vajhøj

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


Joshua Cranmer gave a good rule:

"If you have to make your grader (reader) think about whether or not
it's correct, that is not a good sign."

I will supplement with:

"If the code requires the reader to have read the JLS, then it
is probably not as readable as it should be."

Arne
 
A

Arne Vajhøj

Tom McGlynn said:
For me at least this tends to buggy code when I need to modify this
line to
x = weight*a[--i]; (sic)


Maybe we should refrain from using this argument:

»You should not use ... in code, because when you
later have to modify the code in that way, it
would be wrong (if one would forget to change
this part, too).«

For example, whats wrong in the following sentence?

»The girl takes the book.«

Well, look: There is nothing actually wrong, but one
should not use »takes«, because when one later has
to change »The girl« into »The girls«, it would be wrong:

»The girls takes the book.«

-- Such a way of reasoning surely is deemed to be ridiculous.

So why should one adopt it for source code?

The author of source code usually cannot foresee the
direction of possible future changes, so he should solve the
task at hand not a possible future task. When another
programmer later has the task to modify the code, it is
/his/ duty to do this correctly.


If there exists a construct in the English language that are
more robust to changes, then we should use it.

If a more robust construct does not exist in Java, then we
can not do anything about it.

We do the best we can within the constraints given.

Arne
 
S

Stefan Ram

Arne Vajhøj said:
Two identical calls are not so nice.

(I have not read the whole thread, so I am sorry
if the following suggestion was already given.)

One could also write this as:

String line; for( boolean looping = true; looping; )
{ line = rdr.readLine();
looping = line != null; }

.
 
M

Martin Gregorie

The scope problem rarely has any practical impact.

And the problem seems a a natural "while problem".
Precisely the reason I said that extending 'while' statements to allow:

while(<optional declaration;> boolean-expression)
action-statement

would be a useful extension to Java syntax.
 
L

Lew

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

Unless you don't know Java.

JLS §15.7
Joshua Cranmer gave a good rule:

"If you have to make your grader (reader) think about whether or not
it's correct, that is not a good sign."

I will supplement with:

"If the code requires the reader to have read the JLS, then it
is probably not as readable as it should be."

Reading Java code at all, and certainly writing or maintaining it requires the
reader to have read the JLS. No one should represent themselves as Java
programmers without having done so at least once. No one wishing proficiency
in Java programming should stop at once.

Order of evaluation is one of the first things to learn in a language, along
with the syntax for literals and what the pre- and post-fix auto-increment and
-decrement operators do. I cited the JLS only as a remedial aid for folks to
bone up on the essentials. One shouldn't really have to refer to it for this
basic matter. Not that it hurts to do so - the masters are the ones who go
back and refer to the basic information, e.g., chapters of the JLS and the
tutorials, regularly and frequently.
 
D

Daniel Giaimo

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

Unless you don't know Java.

JLS §15.7
Joshua Cranmer gave a good rule:

"If you have to make your grader (reader) think about whether or not
it's correct, that is not a good sign."

I will supplement with:

"If the code requires the reader to have read the JLS, then it is
probably not as readable as it should be."

Reading Java code at all, and certainly writing or maintaining it
requires the reader to have read the JLS. No one should represent
themselves as Java programmers without having done so at least once. No
one wishing proficiency in Java programming should stop at once.

ROTFLMAO. I am not now, nor do I ever intend to become, a "Java
programmer". That way lies career suicide. I am a software engineer who
happens to use Java in a lot of his work.

In my opinion, there are two things an engineer should read before
programming in a language: A simple tutorial to get the basics of the
syntax down, and a style guide to learn the standard idioms used by other
people who use that language. The only engineers who should even care
that a spec exists are compiler writers.
Order of evaluation is one of the first things to learn in a language,

I would say that order of evaluation is something you should _never_
learn about in any language you program in except for very specific cases
like short-circuiting boolean operators where standard idioms depend on
it. In fact, the best programming languages, e.g. C, specifically choose
not to define order of evaluation in most cases in their spec and leave
it up to the compiler writer to choose an order, or even to choose
different orders in different cases.

--
Dan Giaimo
 
E

Eric Sosman

[...] I am a software engineer who
happens to use Java in a lot of his work.

In my opinion, there are two things an engineer should read before
programming in a language: A simple tutorial to get the basics of the
syntax down, and a style guide to learn the standard idioms used by other
people who use that language. The only engineers who should even care
that a spec exists are compiler writers.

I think that if you program this way you are not an engineer
at all, but merely an imitator. Java allows imitation to carry one
further than many other languages will, but you will eventually hit
a situation from which no amount of half-understood abracadabra will
extricate you. You will *certainly* find yourself debugging code
that somebody else wrote; if all you can do is imitate, all you can
do is repeat the existing bug.

It is true that a certain amount of software can be written and
debugged and enhanced through pure imitation; I've done it myself in
more than half a dozen languages I didn't really know and couldn't
(or didn't want to) take the time to learn. If you must fix the code
quickly and it's written in Babel-7, by all means fake your way
through. But if you use a language "a lot" (your phrase), and you do
not take the time to learn what you are doing, you are not an engineer
but just playing one on TV.
 
A

Arne Vajhøj

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

Unless you don't know Java.

JLS §15.7
Joshua Cranmer gave a good rule:

"If you have to make your grader (reader) think about whether or not
it's correct, that is not a good sign."

I will supplement with:

"If the code requires the reader to have read the JLS, then it
is probably not as readable as it should be."

Reading Java code at all, and certainly writing or maintaining it
requires the reader to have read the JLS. No one should represent
themselves as Java programmers without having done so at least once. No
one wishing proficiency in Java programming should stop at once.

Order of evaluation is one of the first things to learn in a language,

Let me quote Java Coding Convention:

<quote>
10.5.1 Parentheses

It is generally a good idea to use parentheses liberally in expressions
involving mixed operators to avoid operator precedence problems. Even if
the operator precedence seems clear to you, it might not be to
others-you shouldn't assume that other programmers know precedence as
well as you do.
along with the syntax for literals and what the pre- and post-fix
auto-increment and -decrement operators do. I cited the JLS only as a
remedial aid for folks to bone up on the essentials. One shouldn't
really have to refer to it for this basic matter. Not that it hurts to
do so - the masters are the ones who go back and refer to the basic
information, e.g., chapters of the JLS and the tutorials, regularly and
frequently.

No.

Masters are those that can write code so readable that even
people with a poor understanding of the languages can read it.

Arne
 

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,773
Messages
2,569,594
Members
45,124
Latest member
JuniorPell
Top