Имеет ли PHP оценку короткого замыкания?


учитывая следующий код:

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

Если is_valid($string) возвращает false, интерпретатор php все еще проверяет более поздние условия, такие как up_to_length($string)? Если да, то почему он делает дополнительную работу, когда это не нужно?

8 57

8 ответов:

да, интерпретатор PHP является "ленивым", что означает, что он будет делать минимальное количество сравнений, возможных для оценки условий.

Если вы хотите проверить, попробуйте это:

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

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

Да, это делает. Вот небольшой трюк, который опирается на оценку короткого замыкания. Иногда у вас может быть небольшой оператор if, который вы предпочитаете писать как троичный, например:

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

можно переписать как:

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

а затем, что если есть блокировка также требуется какая-то функция будет работать?

    if ($confirmed) {
        do_something();

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

ну, переписывание как тернарное все еще возможно, из-за оценки короткого замыкания:

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

в этом случае выражение (do_something () / / true) ничего не делает, чтобы изменить общий результат тернарного, но гарантирует, что do_something () запускается только в том случае, если $confirmed имеет значение true.

нет, он больше не проверяет другие условия, если первое условие не выполняется.

таким образом, в резюме:

побитовые операторы & и/
Они всегда оценивают оба операнда.

Логическими операторами являются AND, OR, & & и|/
И И ИЛИ всегда оценивают оба операнда.

&& и / / оценивайте только правую сторону, если это необходимо.

Я создал свою собственную логику оценки короткого замыкания, к сожалению, это не похоже на синтаксис javascripts quick, но, возможно, это решение, которое вы можете найти полезным:

$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

Я не могу вспомнить, откуда я получил следующую логику, но если вы сделаете следующее;

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

вы можете пропустить необходимость снова писать переменную true condition, после знака вопроса, например:

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

как очень важное наблюдение при использовании Тернарный Оператор таким образом, Вы заметите, что если сравнение будет сделано, оно просто передаст значение этого сравнения, так как нет только одной переменной. Например:

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

нет. Это всегда хорошее место, чтобы оптимизировать порядок условия.

Примечание: Если вы хотите избежать ленивой проверки и запустить каждую часть условия, в этом случае вам нужно использовать логический и такой:

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

это полезно, когда вам нужно, например, вызвать две функции, даже если первая возвратила false.

мой выбор: не оценка короткого замыкания доверия в PHP...

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

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

вторая часть в состоянии 1 || saySomething() не имеет значения, потому что это всегда будет возвращать true. К сожалению saySomething() оценивается и выполняется.

может быть, я неправильно понял точную логику коротких замыканий выражений, но это не похоже на "это сделает минимальное количество возможных сравнений" to мне.

кроме того, это не только проблема производительности, если вы выполняете задания внутри сравнений или если вы делаете что-то, что имеет значение, кроме простого сравнения, вы можете закончить с разными результатами.

в любом случае... быть осторожным.