2

In the spirit of seeing Short-circuit evaluation like Python's "and" while storing results of checks I decided to see how this could be best solved in PHP but I've run into an issue.

unexpected

<?php
function check_a()
{
    return 'A';
}
function check_b()
{
    return 'B';
}
function check_c()
{
    return 'C';
}

if($a = check_a() && $b = check_b() && $c = check_c())
{
    var_dump($a);
    var_dump($b);
    var_dump($c);
}

Results in:

bool(true)
bool(true)
string(1) "C"

code for what I wanted to happen

<?php
function check_a()
{
    return 'A';
}
function check_b()
{
    return 'B';
}
function check_c()
{
    return 'C';
}

// if(($a = check_a()) && ($b = check_b()) && $c = check_c()) // equivalent to line below
if(($a = check_a()) && ($b = check_b()) && ($c = check_c()))
{
    var_dump($a);
    var_dump($b);
    var_dump($c);
}

Results in:

string(1) "A"
string(1) "B"
string(1) "C"

Why does the unexpected example act in this way?

Community
  • 1
  • 1
MonkeyZeus
  • 20,375
  • 4
  • 36
  • 77
  • 3
    you do realize that you're assigning rather than comparing. – Funk Forty Niner Sep 21 '16 at 15:23
  • @Fred-ii- — Isn't that the point of what they are trying to do? – Quentin Sep 21 '16 at 15:24
  • @Quentin I....er.... guess *lol*. my bad. – Funk Forty Niner Sep 21 '16 at 15:25
  • 1
    Pretty sure the answer is in http://php.net/manual/en/language.operators.precedence.php … but I don't want to try to unpick it right now to figure out exactly how. – Quentin Sep 21 '16 at 15:25
  • @Fred-ii- Yes I know the difference between `=`, `==`, and `===`. Please try my code and change `check_a()` to `return '';` and you will see what I am asking about – MonkeyZeus Sep 21 '16 at 15:25
  • @MonkeyZeus I made a mistake earlier. However, you mention *"change `check_a()` to `return '';`"* - How is the `return '';` used and where and is it relevant to the question? You didn't post that in your question. However, Quentin and others below have provided you with answers. – Funk Forty Niner Sep 21 '16 at 15:30

2 Answers2

4

This is a question of operator precedence. An assignment expression returns the assigned value, so you would expect to get A and B for the first two operations. The reason you're getting boolean true instead is that the && operator has a higher precedence than the assignment operator, so in the original expression

$a = check_a() && $b = check_b() && $c = check_c()

$a gets the value of check_a() && $b = check_b() && $c = check_c(),

$b gets the value of check_b() && $c = check_c(),

and $c gets the value of check_c().

The expressions check_a() && $b = check_b() && $c = check_c(), and check_b() && $c = check_c() return boolean true, because the use of the && operator causes the expressions to be evaluated as booleans, and all components of the expressions joined by && evaluate to true.

To get the results you expect, you can add parentheses as you did, or you can use the and logical operator instead of &&, because it has a lower precedence than the assignment operator.

if($a = check_a() and $b = check_b() and $c = check_c()) {
Don't Panic
  • 41,125
  • 10
  • 61
  • 80
2

The result of a boolean && is a bool! && binds stronger than =. Therefore $b gets assigned ('B' && $c) which is a bool... Same obviously with $a...

arkascha
  • 41,620
  • 7
  • 58
  • 90