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?

6
  • 3
    you do realize that you're assigning rather than comparing. Commented Sep 21, 2016 at 15:23
  • @Fred-ii- — Isn't that the point of what they are trying to do? Commented Sep 21, 2016 at 15:24
  • @Quentin I....er.... guess lol. my bad. Commented Sep 21, 2016 at 15:25
  • 1
    Pretty sure the answer is in 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. Commented Sep 21, 2016 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 Commented Sep 21, 2016 at 15:25

2 Answers 2

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()) {
Sign up to request clarification or add additional context in comments.

Comments

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...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.