Velocity Reviews > Java > Question on associativity and precedence

# Question on associativity and precedence

ankur
Guest
Posts: n/a

 07-04-2008
int[] z = {10,20,30,40,50};
int index = 4;
z[index] = index = 2;

System.out.println(z[0]);
System.out.println(z[1]);
System.out.println(z[2]);
System.out.println(z[3]);
System.out.println(z[4]);

This code gives

10
20
30
40
2

Why does it not give:
10
20
2
40
50

Why z[2] is not assigned 2?? How can this be explained in terms of
associativity and precedence rules.

Mark Space
Guest
Posts: n/a

 07-04-2008
ankur wrote:

> Why z[2] is not assigned 2?? How can this be explained in terms of
> associativity and precedence rules.

Good question. I think this is the answer:

<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.1>

"If the left-hand operand is an array access expression ... then:

* First, the array reference subexpression of the left-hand operand
array access expression is evaluated.... "

So that's the order because the JLS says it is.

For assignment, a = (b = c); if "a" is an expression (?, I think
"expression" is correct, the same section talks about fields too) a is
evaluated first. Then "(b = c)" is evaluated. I'd assume that if "b"
is an expression, it will be evaluated before "c". I'd have to look-up
which one of those is precedence, and which is associativity. It may be
both one or the other, too, I suppose.

Finally, the assignments occur.

Roedy Green
Guest
Posts: n/a

 07-04-2008
On Fri, 4 Jul 2008 12:30:22 -0700 (PDT), ankur
<(E-Mail Removed)> wrote, quoted or indirectly quoted someone
who said :

>z[index] = index = 2;

first of all, don't use cascaded assignment operators. The only time
you see them in on exams.

see http://mindprod.com/jgloss/precedence.html

You will learn that = in evaluated right to left.

Java has a horrible hodgepodge precedence and left to right and right
to left operators mainly inherited from C.
--

The Java Glossary
http://mindprod.com

Joshua Cranmer
Guest
Posts: n/a

 07-04-2008
ankur wrote:
> int[] z = {10,20,30,40,50};
> int index = 4;
> z[index] = index = 2;

Generated bytecode (roughly):

iconst_4 push 4 on to the stack
istore <index> store the top of the stack (4) into index
iconst_2 push 2 on to the stack
dup duplicate the top element (2) on the stack
istore <index> store the top of the stack (2) into index
iastore store the top of the stack into the index denoted by the
second value on the stack of the array denoted by the
third item of the stack.

In general, an operand is resolved before any of the operands to the
right of it and after any operand to its left, such that an assignment
to its right does not affect any usages of the variable to its left.
Left and right are defined, of course, in terms of the JLS and are more
properly before and after, but human notation makes left/right clearer.

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Joshua Cranmer
Guest
Posts: n/a

 07-04-2008
Roedy Green wrote:
> On Fri, 4 Jul 2008 12:30:22 -0700 (PDT), ankur
> <(E-Mail Removed)> wrote, quoted or indirectly quoted someone
> who said :
>
>> z[index] = index = 2;

>
> first of all, don't use cascaded assignment operators. The only time
> you see them in on exams.

Not quite true: I occasionally use something in the form of "x = y = 0"
myself, but it tends to be rare.

Certainly, it's not at as stupid as the ageless C question "What does
i=i++ evaluate to?"

--
Beware of bugs in the above code; I have only proved it correct, not
tried it. -- Donald E. Knuth

Mark Space
Guest
Posts: n/a

 07-05-2008
>

Reading the JLS a bit more, I found this:

<http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.1>

"Otherwise, three steps are required:

* First, the left-hand operand is evaluated to produce a variable.
If this evaluation completes abruptly, then the assignment expression
completes abruptly for the same reason; the right-hand operand is not
evaluated and no assignment occurs.
* Otherwise, the right-hand operand is evaluated. If this
evaluation completes abruptly, then the assignment expression completes
abruptly for the same reason and no assignment occurs. "

"Otherwise" means if the left hand operand of an assignment is neither a
field or an array.

But the point is the operand is evaluated "first to produce a variable."
This is implies to me that there are two passes over a Java
expression. First, to produce variables. This pass seems to go left to
right. (I can't think of a case where grouping or precedence would make
it go differently.)

Then in the second pass the variables are evaluated with the specified
order of operations. All expressions are evaluated here.

The exception in both cases seems to be the short circuit operators,
which may not evaluate their right hand variables or operations at all,
depending on the value of the left hand expression.

To me, that latter bit implies that expressions involving || and &&
might evaluate differently than the OP's example.

Getting back on track a bit:

Joshua Cranmer wrote:

> Generated bytecode (roughly):
>
> iconst_4 push 4 on to the stack
> istore <index> store the top of the stack (4) into index
> iconst_2 push 2 on to the stack
> dup duplicate the top element (2) on the stack
> istore <index> store the top of the stack (2) into index
> iastore store the top of the stack into the index denoted by

I think the compiler could choose to evaluate "aload <z>" in a different
order of the JLS were different. Get rid of the iconst_4 and move the
evaluation of aload <z> down a bit and you get the effect the OP seems
to be expecting. It's even one less byte code, I think. The compiler
is doing extra work to conform to the JLS.