First off, regarding associativity, I cede the point. The three of you (weed, traq and laserlight) all agree, and so does the internet. I've probably always assumed it was about operands because that removes all ambiguity in evaluation order between operands and by extension to operators.
traq;11036551 wrote:
$x * 2. Regardless of which order the operands are evaluated in, you add one and subtract one: a no-op
This is not true though.
x-- + ++x:
RHS before LHS:
- RHS: x becomes (x+1), LHS: x is now (x+1) afterwards decrease by 1 to (x): result: x => x, statement: (x+1) + (x + 1)
LHS before RHS:
- LHS: use x in the statement, dec x to (x-1), RHS: inc (x-1) to x, use x: x => x, statement: x + x
The result differs by 2.
I do agree that the only thing that makes things right or wrong is their definition. But as weedpacket states, without a clear definition, you have potential for behaviour that will change in future versions. At best it is "only" lacking in documentation or a documentation error. Still, I find both the javascript way of handling things and the C++ way of handling things straightforward, simple and easily predictable. I like both, even though they are different. Do note that neither C++ (and I'd guess C) nor javascript agree on all points, and that both disagree with php on some points.
C++ evaluates all operators of top precedence before operators of lower precedence. For the sake of simplicity, I will refer to this as hard precedence. Pre / post operators affect their variables before or after the statement.
Javascript evaluates operands from left to right while resolving precedence as needed. Pre / post operators affect their values after the expression (i.e. the post or pre operator and its variable) is evaluated.
Back to php:
While it could be "right" to
- Always evaluate operands left to right
- Except if the left operand is a variable and the right operand is an expression, then reverse order
assuming this was defined and documented.
PHP has behaviour which sometimes means left before right, sometimes right before left, which I personally believe is overly complicated, weird etc. They may obviously define whatever behaviour they wish. But either way, I will still claim their current behaviour is a bug, and I'm rather certain it all comes from them NOT having defined (and documented) exactly what is expected while evaluating expressions (or more noteably, their operands). Straight from php.net on operator precedence
Parentheses may be used to force precedence
Yet, they do not always, namely in the exact same situation that has been the show case from the start
$x = 5;
$y = ($x) + ++$x;
If parenthese is indeed used to force precedence, ($x) should be evaluated before anything else. Still, it is not. At the same time, non-parenthesized expressions that should be evaluated before addition, but would always be evaluated later than any parenthesized expression do change the outcome even though they are identity operators under given circumstances:
- integer cast for integers is an identity operation but changes behaviour: (int) 5 === 5
- multiplication by 1 is an identity operation for all integers: 1 5 = 5 1 = 5
$x = 5;
$y = 1*$x + ++$x;
$x = 5;
$y = (int) $x + ++$x;
This last block of code would both evaluate the left operand of + before the right operand. Assuming this behaviour is defined and documented, it is "right" (although I will continue to argue that it would make sense to change it into something that is inline with maths in general and either javascript or C). Mainly for the fact that it gives you one single edge case where RHS is evaluated before LHS, while LHS is always otherwise the norm. But in combination with the lack of respect of forcing evaluation precedence through the use of parenthesis, I will claim it is a bug. The block above with ($x) would evaluated the right operand of + before the left, even though () is supposed to force precdence.
And once again, they could of couse define this behaviour to be "correct", which would make it "right". If they ever do, and put it in the docs, I will simply keep my thoughts to myself on the matter.
Not sure what post this came from, but at some point Traq wrote
Traq wrote:
// first, operator precedence.
// note that I was wrong when I assumed ++ had a higher precedence than +:
// in fact, ++ is not an arithmetic operator at all (++/-- have their own operator type).
That you may consider it other than an arithmetic operator changes nothing. It still has higher precedence than addition. It is listed on the page of operator precedence at php.net alongside casts and error supression. The only thing that may confuse things is that "operator precdence" isn't enough to determine in which order operators are evaluated.
2 + 3 + 4 * 5
May be evaluated as
2 + 3: 5
4 * 4: 20
5 + 20: 25
or as
4 * 5: 20
2 + 3: 5
5 + 20: 25