44

The code my friend sends me is:

echo '1+1='.(1+1==2?2:1+2==2?3:2);

Why is it 3?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ismail
  • 8,904
  • 3
  • 21
  • 39
  • 20
    Read up on "operator binding", "operator precedence", and "order of operations". Some judiciously placed parentheses will solve the problem. – SaganRitual Jun 04 '14 at 14:47
  • http://www.php.net/manual/en/language.operators.precedence.php – Marc B Jun 04 '14 at 14:47
  • Ah... I see what it's doing. I was trying in JS. – Popnoodles Jun 04 '14 at 14:47
  • As @GreatBigBore says, doing echo '1+1='.(1+1==2?2:(1+2==2?3:2)); prints `1+1=2` – Guillermo Gutiérrez Jun 04 '14 at 14:51
  • 10
    Probably comes from this recent question on Code Golf - http://codegolf.stackexchange.com/a/28892 – laurent Jun 04 '14 at 15:56
  • possible duplicate of [nested php ternary trouble: ternary output != if - else](http://stackoverflow.com/questions/4807454/nested-php-ternary-trouble-ternary-output-if-else), also http://stackoverflow.com/q/20559150/7586 , http://stackoverflow.com/questions/18611985/understanding-nested-ternary-operators , and many others. – Kobi Jun 05 '14 at 05:45

1 Answers1

87

PHP's evaluation of the ternary (or conditional) operator is a bit different from that of other languages.

1+1==2 ? 2 : 1+2==2 ? 3 : 2

Most languages (e.g. JavaScript) would evaluate this as:

(1+1==2) ? (2) : ( (1+2==2) ? (3) : (2) ) 
=> 2

PHP, however, evaluates this as:

( (1+1==2) ? (2) : (1+2==2) ) ? (3) : (2)
=> 3

So because (1+1==2) evaluates to true, the result of the first ternary expression evaluates to 2, and that result is then passed to the second ternary expression, which evaluates to 3.

This behavior is alluded to in the documentation:

It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious…

The Wikipedia article on the ?: operator also mentions this:

Due to an unfortunate error in the language grammar, the implementation of ?: in PHP uses the incorrect associativity when compared to other languages…

The reason is that nesting two conditional operators produces an oversized condition with the last two options as its branches: c1 ? o1 : c2 ? o2 : o3 is really ((c1 ? o1 : c2) ? o2 : o3). This is acknowledged and will probably not change.

Community
  • 1
  • 1
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331