• Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Order of Evaluation - General Rules

 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have been trying to really master order of evaluation in complex expressions. As far as I can tell, the rules include operator precedence, operator associativity, left then right evaluation of binary operands, shortcut evaluation of certain logical operators, and ???

Is there a good write-up showing exactly how these rules play into each other?

Just as an example, && and < have lower precedence than ++, so why doesn't
(i < 4 && ++i > 4) always increment i before < and && are evaluated at all?
On the other hand,
int index = 4;
a[index] = index = index-2;
changes a[4], not a[2], so [] is evaluated before the operands of the right-hand =.

I can answer this stuff from a compiler (abstract syntax tree) perspective, but not from a language rules perspective.
 
William Brogden
Author and all-around good cowpoke
Rancher
Posts: 13071
6
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The JLS chapter on expressions looks like heavy reading but should answer your question.
Bill
 
David Harkness
Ranch Hand
Posts: 1646
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Mike Gershman:
Just as an example, && and < have lower precedence than ++, so why doesn't
(i < 4 && ++i > 4) always increment i before < and && are evaluated at all?
Precedence order doesn't get applied across the entire expression. In other words, just because ++ has higher precedence than < doesn't mean ++ will be applied before all < operators in the entire expression -- only before <'s in the same subexpression.

In this case, the compiler first splits the above into two subexpressions ("i < 4" and "++i > 4") to be boolean anded after separate evaluation. They are evaluated in left-to-right order, so "i < 4" goes before "++i > 4". Of course, "++i" is evaluated before "> 4" due to precedence, but "i < 4" is done first due to LtR ordering.
 
Mike Gershman
Ranch Hand
Posts: 1272
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Precedence order doesn't get applied across the entire expression. ... only ... in the same subexpression


Then why, in
int index = 4;
a[index] = index = index-2;
does a[4], not a[2], get changed? = is right-associative.

JLS 15.7 may be the last word on evaluation order, but it's not easy to follow and it doesn't have much to say about how the different rules work together in a non-trivial expression. Is there another exposition available?
 
Marilyn de Queiroz
Sheriff
Posts: 9066
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Peter van der Linden has a good explanation in his book Just Java 2. Unfortunately I can't quote it all here.

"There are three factors that influence the ultimate value of an expression in any algorithmic language, and they work in this order: precedence, associativity, and order of evaluation...."

"Precedence says that some operations bind more tightly than others...."

"Associativity is the tie breaker for deciding the binding when we have several operators of equal precedence strung together...."

"Order of evaluation tells us the sequence for each operator in which the operands are evaluated. In a string left-to-right language like Java, the order of evaluation tells us that in ( i = 2 ) * i++ , the left operand to the multiplication will be evaluated before the right operand, ..."

Seems like a good reason to write simple, readable code that doesn't require an expert to figure out what you're trying to do.
[ December 26, 2004: Message edited by: Marilyn de Queiroz ]
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yup, back when I was switching between languages that did or did not have any precedence rules, I got in the habit of splitting up the calculation or making the order explicit with parens any time I mix operators at all. I don't trust myself or the next reader (or the compiler, entirely) to get it right otherwise.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic