Asked  7 Months ago    Answers:  5   Viewed   41 times

I'm trying to understand the behavior of or operator. Please see the below examples:

$e = false || true;
var_dump($e);

Output is as expected: bool(true);

$f = false or true;
var_dump($f);

Output is as expected: bool(false). I understood this in a way that the = has a higher precedence than the Or, so that's why the $f is assigned to false.

But the below code works quite opposite of what I thought. I thought that the $foo will be assigned to 5 and then compared to itself. But the $foo is getting assigned only when if the $foo is set that means it is checking if the $foo is assigned to anything before, assign 5 to it.

$foo or $foo = 5; 

Can anyone explain why this is so?

 Answers

70

The basics:

  1. An assignment expression results in the assigned value.

    What does that mean? $foo = 'bar' is an expression, in which the assignment operator = assigns a value. An expression always returns a value itself. Just like the expression 1 + 2 results in the value 3, the expression $foo = 'bar' results in the value 'bar'. That's why this works:

    $foo = $bar = 'baz'; // which is: $foo = ($bar = 'baz');
    
  2. Boolean operations are short-circuiting operations. Both sides are not always evaluated if they don't need to be. true || false is always true overall, since the lefthand operand is true, so the whole expression must be true. false is not even being evaluated here.

  3. Operator precedence dictates in which order parts of an expression are grouped into sub-expressions. Higher precedence operators are grouped with their operands before lower precedence operators.

Therefore:

$e = false || true;

false || true is being evaluated, which results in the value true, which is assigned to $e. The || operator has a higher precedence than =, therefore false || true is grouped into an expression (as opposed to ($e = false) || true).

$f = false or true;

Here now or has a lower precedence than =, which means the assignment operation is grouped into one expression before or. So first the $f = false expression is evaluated, the result of which is false (see above). So then you have the simple expression false or true which is evaluated next and results in true, but which nobody cares about.

The evaluation works like this:

1. $f = false or true;
2. ($f = false) or true;  // precedence grouping
3. false or true;         // evaluation of left side ($f is now false)
4. true;                  // result

Now:

$foo or $foo = 5; 

Here, again, $foo = 5 has a higher precedence and is treated as one expression. Since it occurs on the right side of the or operator, the expression is only evaluated if necessary. It depends on what $foo is initially. If $foo is true, the right hand side will not be evaluated at all, since true or ($foo = 5) must be true overall. If $foo has a falsey value initially though, the right hand side is evaluated and 5 is assigned to $foo, which results in 5, which is true-ish, which means the overall expression is true, which nobody cares about.

1. $foo or $foo = 5;
2. $foo or ($foo = 5);   // precedence grouping
3. false or ($foo = 5);  // evaluation of left side
4. false or 5;           // evaluation of right side ($foo is now 5)
5. true;                 // result
Wednesday, March 31, 2021
 
jeremyharris
answered 7 Months ago
88

It evaluates to the left operand if the left operand is truthy, and the right operand otherwise.

In pseudocode,

foo = bar ?: baz;

roughly resolves to

foo = bar ? bar : baz;

or

if (bar) {
    foo = bar;
} else {
    foo = baz;
}

with the difference that bar will only be evaluated once.

You can also use this to do a "self-check" of foo as demonstrated in the code example you posted:

foo = foo ?: bar;

This will assign bar to foo if foo is null or falsey, else it will leave foo unchanged.

Some more examples:

<?php
    var_dump(5 ?: 0); // 5
    var_dump(false ?: 0); // 0
    var_dump(null ?: 'foo'); // 'foo'
    var_dump(true ?: 123); // true
    var_dump('rock' ?: 'roll'); // 'rock'
?>

By the way, it's called the Elvis operator.

Elvis operator

Wednesday, March 31, 2021
 
van_folmert
answered 7 Months ago
88

Because it's ambiguous, i.e. it can be interpreted in 2 different ways:

  • Call test() on a new X instance (the one that you want):

    $object = new X();
    $x      = $object->test();
    
  • Create a new instance of a class name returned by method test() on the object returned by function X():

    $object = X();
    $class  = $object->test();
    $x      = new $class();
    

Strangely enough, there's actually no way to write a one-liner for the second case ... the following won't work:

new (X()->test());   // syntax error
new (X()->test())(); // syntax error

But still, you get the idea.

Wednesday, March 31, 2021
 
devo
answered 7 Months ago
10

That's a bitwise OR operator. It's behavior on strings is explained here: http://php.net/manual/en/language.operators.bitwise.php#example-107

<?php
echo 12 ^ 9; // Outputs '5'

echo "12" ^ "9"; // Outputs the Backspace character (ascii 8)
                 // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

echo "hallo" ^ "hello"; // Outputs the ascii values #0 #4 #0 #0 #0
                        // 'a' ^ 'e' = #4

echo 2 ^ "3"; // Outputs 1
              // 2 ^ ((int)"3") == 1

echo "2" ^ 3; // Outputs 1
              // ((int)"2") ^ 3 == 1
?>
Wednesday, March 31, 2021
 
avon_verma
answered 7 Months ago
68

The comma operator evaluates every operand but only returns the result of the last evaluation. It can be used to initialize multiple variable in a for loop.

var str = "Hello, World!";
for(var i = 0, len = str.length; i < len; i++)
    console.log(str.charAt(i));

Edit: As pointed out in the comments, this isn't a true example of the comma operator, this is just the var. You can see this page for actual examples.

Thursday, August 12, 2021
 
Heisenberg
answered 3 Months 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 :