Left association of the left three

In the PHP manual, I find the following "note made by the user" in the "Operators" section.

Note that in php, the ternary operator ?: has left associativity, unlike C and C ++, where it has right associativity.

You cannot write code like this (as you are used to in C / C ++):

<?php $a = 2; echo ( $a == 1 ? 'one' : $a == 2 ? 'two' : $a == 3 ? 'three' : $a == 4 ? 'four' : 'other'); echo "\n"; // prints 'four' 

I really tried and it really prints four . However, I could not understand the reason for this and still feel that it should print two or other .

Can someone explain what is happening here and why it prints "four"?

+24
ternary-operator php associativity
Dec 13 '13 at 4:33
source share
4 answers

In any normal language, the ternary operator is right-associative, so you expect your code to be interpreted like this:

 $a = 2; echo ($a == 1 ? 'one' : ($a == 2 ? 'two' : ($a == 3 ? 'three' : ($a == 4 ? 'four' : 'other')))); # prints 'two' 

However, the PHP ternary operator is strangely left-associative, so your code is actually equivalent to this:

 <?php $a = 2; echo (((($a == 1 ? 'one' : $a == 2) ? 'two' : $a == 3) ? 'three' : $a == 4) ? 'four' : 'other'); # prints 'four' 

If this is not yet clear, the assessment will look like this:

 echo ((((FALSE ? 'one' : TRUE) ? 'two' : $a == 3) ? 'three' : $a == 4) ? 'four' : 'other'); echo ((( TRUE ? 'two' : $a == 3) ? 'three' : $a == 4) ? 'four' : 'other'); echo (( 'two' ? 'three' : $a == 4) ? 'four' : 'other'); echo ( 'three' ? 'four' : 'other'); echo 'four'; 
+17
Jul 06 '16 at 18:24
source share

Because your whole expression is evaluated as if it (......) ? 'four' : 'other' (......) ? 'four' : 'other' . Since the first element is probably something believable, it gives you the 'four' . In more well-known languages, where ?: Has the right associativity, the whole expression is evaluated as if it were $a == 1 ? 'one' : (......) $a == 1 ? 'one' : (......) , where if $a not 1 , you continue to check other things.

+17
Dec 13 '13 at 4:39
source share

If you add parentheses, the problem will be solved. Take a look at the following example:
Without parentheses, the class is always D when the labels are greater than 50, but is great for labels <= 49.
To make the program work properly, I added parentheses. It is very easy to know how many brackets should be entered if it is typed like this.

 <?php $marks_obtained = 65; $grade = null; //Use parentheses () otherwise the final grade shown will be wrong. //Excluding the first line, for each additional line, //we add a parenthesis at the beginning of each line and a parenthesis at the end of the statement. echo $grade = $marks_obtained >= 90 && $marks_obtained <= 100 ? "A+" : ($marks_obtained <= 89 && $marks_obtained >= 80 ? "A" : ($marks_obtained <= 79 && $marks_obtained >= 70 ? "B" : ($marks_obtained <= 69 && $marks_obtained >= 60 ? "C" : ($marks_obtained <= 59 && $marks_obtained >= 50 ? "D" : "F")))) ?> 
0
Oct. 16 '14 at 18:57
source share

I could not wrap my head in an example from:

https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/

So, I came here, and I still could not wrap it around, so I had to go through it.

@amadan has the best answer, imo.

It prints a horse, not a train.

 // 0 $arg = 'T'; $vehicle = $arg == 'B' ? 'bus' : $arg == 'A' ? 'airplane' : $arg == 'T' ? 'train' : $arg == 'C' ? 'car' : $arg == 'H' ? 'horse' : 'feet' ; // 1 $vehicle = > FALSE ? 'bus' : $arg == 'A' ? 'airplane' : $arg == 'T' ? 'train' : $arg == 'C' ? 'car' : $arg == 'H' ? 'horse' : 'feet' ; // 2 $vehicle = FALSE ? 'bus' : > FALSE ? 'airplane' : $arg == 'T' ? 'train' : $arg == 'C' ? 'car' : $arg == 'H' ? 'horse' : 'feet' ; // 3 $vehicle = > (FALSE? 'bus' : FALSE? 'airplane' : TRUE)? 'train' : $arg == 'C' ? 'car' : $arg == 'H' ? 'horse' : 'feet' ; // 4 $vehicle = > true ? 'train' : $arg == 'C' ? 'car' : $arg == 'H' ? 'horse' : 'feet' ; // 5 $vehicle = > ('train' : $arg == 'C') ? 'car' : $arg == 'H' ? 'horse' : 'feet' ; // 6 $vehicle = > (true ? 'car' : $arg == 'H') ? 'horse' : 'feet' ; // 7 $vehicle = > (true) ? 'horse' : 'feet' ; 

You can see what left associative tools are in step 5, if I understand correctly.

0
Aug 13 '17 at 18:10
source share



All Articles