Asked  7 Months ago    Answers:  5   Viewed   40 times

In the PHP manual, I find the following 'user contributed note' under "Operators".

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

You cannot write code like this (as you may have accustomed 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 actually try it and it really prints four. However I could not understand the reason behind it and still feel it should print two or other.

Can someone please explain what is happening here and why it is printing 'four'?

 Answers

97

In any sane language, the ternary operator is right-associative, such that you would 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 weirdly left-associative, such that 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'

In case it still isn't clear, the evaluation goes 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';
Wednesday, March 31, 2021
 
elias
answered 7 Months ago
58

When your first argument is null, they're basically the same except that the null coalescing won't output an E_NOTICE when you have an undefined variable. The PHP 7.0 migration docs has this to say:

The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.

Here's some example code to demonstrate this:

<?php

$a = null;

print $a ?? 'b'; // b
print "n";

print $a ?: 'b'; // b
print "n";

print $c ?? 'a'; // a
print "n";

print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "n";

$b = array('a' => null);

print $b['a'] ?? 'd'; // d
print "n";

print $b['a'] ?: 'd'; // d
print "n";

print $b['c'] ?? 'e'; // e
print "n";

print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "n";

The lines that have the notice are the ones where I'm using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.

Execute the code: https://3v4l.org/McavC

Of course, this is always assuming the first argument is null. Once it's no longer null, then you end up with differences in that the ?? operator would always return the first argument while the ?: shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.

So:

$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'

would then have $a be equal to false and $b equal to 'g'.

Wednesday, March 31, 2021
 
Shibbir
answered 7 Months ago
35

You need to add some parenthesis.

$b = 'a';
$c = 'd';
echo ($b == 'a') ? 2 : ($c == 'a' ? 1 : 0);
Saturday, May 29, 2021
 
Corsair
answered 5 Months ago
98

Yes, you can rely on this (not only in C# but in all (that I know) other languages (except PHP … go figure) with a conditional operator) and your use-case is actually a pretty common practice although some people abhor it.

The relevant section in ECMA-334 (the C# standard) is 14.13 §3:

The conditional operator is right-associative, meaning that operations are grouped from right to left. [Example: An expression of the form a ? b : c ? d : e is evaluated as a ? b : (c ? d : e). end example]

Wednesday, August 11, 2021
 
superfell
answered 3 Months ago
61

C# language specification, version 5, section 6.1.9:

An implicit constant expression conversion permits the following conversions:

  • A constant-expression (§7.19) of type int can be converted to type sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant-expression is within the range of the destination type.

Your first example is a constant expression, because it can be evaluated at compile time. But see section 7.19 for more details:

Only the following constructs are permitted in constant expressions:

  • Literals (including the null literal).

[...]

  • The predefined +, –, *, /, %, <<, >>, &, |, ^, &&, ||, ==, !=, <, >, <=, and >= binary operators, provided each operand is of a type listed above.
  • The ?: conditional operator.
Friday, September 17, 2021
 
Muazam
answered 1 Month ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :