ChatGPT解决这个技术问题 Extra ChatGPT

Does PHP have short-circuit evaluation?

Given the following code:

if (is_valid($string) && up_to_length($string) && file_exists($file)) 
{
    ......
}

If is_valid($string) returns false, does the php interpreter still check later conditions, like up_to_length($string)?
If so, then why does it do extra work when it doesn't have to?

Some reading to go along with all these answers: en.wikipedia.org/wiki/Short-circuit_evaluation
This is referring to the topic of short-circuit evaluation, and different languages handle it differently.
@AJ: Honestly, I'm yet to see a (serious/widely used) programming language that doesn't have short-circuit evaluation for logical and and logical or. Do you have an example?
@delnan - I think what you meant was "Most widely-used programming languages don't implement any eager operators."
@delnan - VB and Fortran come to mind...

Z
Zach Rattner

Yes, the PHP interpreter is "lazy", meaning it will do the minimum number of comparisons possible to evaluate conditions.

If you want to verify that, try this:

function saySomething()
{
    echo 'hi!';
    return true;
}

if (false && saySomething())
{
    echo 'statement evaluated to true';
}

Short circuit evaluation != lazy.
@delnan: This is an example of lazy evaluation. See books.google.com/….
A tiny example, and an arguable one (in the same vein, one could call if statements an example of lazy evaluation). Lazy evaluation is much more general - it applies to every expression everywhere (although you can usually force evaluation without using the value). That book excerpt gets this right.
Do you know of any ways to disable this behaviour ?
@RaduMurzea: short circuiting is not something I expect to be toggled as it can have adverse consequences to an entire program and imported libraries. consider the situation where you check if a variable is set before reading it if (isset($var['index']) && $var['index'] === "something"). if you need to evaluate each condition in a boolean expression, then evaluate and save them before the if statement, then check the results in the if condition.
b
beppe9000

Yes, it does. Here's a little trick that relies on short-circuit evaluation. Sometimes you might have a small if statement that you'd prefer to write as a ternary, e.g.:

    if ($confirmed) {
        $answer = 'Yes';
    } else {
        $answer = 'No';
    }

Can be re-written as:

   $answer = $confirmed ? 'Yes' : 'No';

But then what if the yes block also required some function to be run?

    if ($confirmed) {
        do_something();

        $answer = 'Yes';
    } else {
        $answer = 'No';
    }

Well, rewriting as ternary is still possible, because of short-circuit evaluation:

    $answer = $confirmed && (do_something() || true) ? 'Yes' : 'No';

In this case the expression (do_something() || true) does nothing to alter the overall outcome of the ternary, but ensures that the ternary condition stays true, ignoring the return value of do_something().


D
Das_Geek

Bitwise operators are & and |. They always evaluate both operands.

Logical operators are AND, OR, &&, and ||.

All four operators only evaluate the right side if they need to.

AND and OR have lower precedence than && and ||. See example below.

From the PHP manual:

// The result of the expression (false || true) is assigned to $e
// Acts like: ($e = (false || true))
$e = false || true;

// The constant false is assigned to $f before the "or" operation occurs
// Acts like: (($f = false) or true)
$f = false or true;

In this example, e will be true and f will be false.


"AND and OR always evaluate both operands." -- this is not true. They only have lower precedence than && and || but other than that they have the same semantic as && and ||.
will add good notice from manual: "Note that PHP's boolean operators always return a boolean value... as opposed to other languages that return the value of the last evaluated expression."
a
agm1984

Based on my research now, PHP doesn't seem to have the same && short circuit operator as JavaScript.

I ran this test:

$one = true;

$two = 'Cabbage';

$test = $one && $two;

echo $test;

and PHP 7.0.8 returned 1, not Cabbage.


I think && causes php to cast everything into a boolean, so that $two is cast to true, and then echoed as 1. You would need true||(echo 'no short circuit') to test that (or something like it).
O
Obay

No, it doesn't anymore check the other conditions if the first condition isn't satisfied.


P
Perspective

I've create my own short-circuit evaluation logic, unfortunately it's nothing like javascripts quick syntax, but perhaps this is a solution you might find useful:

$short_circuit_isset = function($var, $default_value = NULL) {
    return  (isset($var)) ? : $default_value;
};

$return_title = $short_circuit_isset( $_GET['returntitle'], 'God');

// Should return type 'String' value 'God', if get param is not set

I can not recall where I got the following logic from, but if you do the following;

(isset($var)) ? : $default_value;

You can skip having to write the true condition variable again, after the question mark, e.g:

(isset($super_long_var_name)) ? $super_long_var_name : $default_value;

As very important observation, when using the Ternary Operator this way, you'll notice that if a comparison is made it will just pass the value of that comparison, since there isn't just a single variable. E.g:

$num = 1;
$num2 = 2;
var_dump( ($num < $num2) ? : 'oh snap' );
// outputs bool 'true'

That logic with the ?: works just like JavaScript/Perl's ||.
Not quite trysys -- the left hand argument seems to be scanned for an expression which is returned if it is true -- regardless of a function around it. (Ex: isset($var) ?: '1' produces $var if the first expression in true).
B
Beto Aveiga

My choice: do not trust Short Circuit evaluation in PHP...

function saySomething()
{
    print ('hi!');
    return true;
}

if (1 || saySomething())
{
    print('statement evaluated to true');
}

The second part in the condition 1 || saySomething() is irrelevant, because this will always return true. Unfortunately saySomething() is evaluated & executed.

Maybe I'm misunderstood the exact logic of short-circuiting expressions, but this doesn't look like "it will do the minimum number of comparisons possible" to me.

Moreover, it's not only a performance concern, if you do assignments inside comparisons or if you do something that makes a difference, other than just comparing stuff, you could end with different results.

Anyway... be careful.


That might be the reason for whether it's about short-circuit evaluation or eagerness. It stops as soon as it knows the result will be false.
Actually I just ran your code and it didn't execute saySomething(). PHP 5.3.13
+1 to grantwparks, saySomething() does not get executed. PHP properly short circuits. I've been writing this sort of code in PHP for the better part of a decade now, I don't recall ever getting hung up on this issue. Occasionally I write more verbose code if I feel a little extra clarity is important, but usually a code comment is enough to cover that concern.
You are right. I ran my own test again and function saySomething() never gets executed. I don't know what could went wrong in my first tests. Sorry :(
Its a proof that php behaviour is consistent. if first value in OR condition is true its obvious if is true it does not process rest of statements its consistent with short circuit behaviour.
P
Patricio Rossi

Side note: If you want to avoid the lazy check and run every part of the condition, in that case you need to use the logical AND like this:

if (condition1 & condition2) {
 echo "both true";
}
else {
 echo "one or both false";
}

This is useful when you need for example call two functions even if the first one returned false.


This is not "the logical AND", it's a bitwise operator. And it may surprise you, because it does not work exactly like the logical &&.
It is the logic AND gate, why you say is not? and yes as I said is not the && or AND. It will not surprise me because I actually know how it works. Simple like checking this table and using the correct return type: 1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0
There's a distinction between the logical and the bitwise AND in PHP; this here is not the logical AND. And even if you know what its rules are, future readers may not.
This is "not" the logical operation asked by OP. Using a single & is a bitwise operation.
You are speaking about operators and I speaking about gates, in PHP both operators are an AND gate, but one is short circuited.