Como posso fazer com que o PHP evite avaliação preguiçosa?
-
22-08-2019 - |
Pergunta
Eu tenho uma pergunta interessante sobre a maneira como o PHP avalia expressões booleanas. Quando você tem, por exemplo,
$expression = $expression1 and $expression2;
ou
if ($expression1 and $expression2)
PHP verifica primeiro se $expression1
avalia para true
. Se não for esse o caso, então $expression2
é simplesmente ignorado para evitar cálculos desnecessários. Em um script que estou escrevendo, tenho:
if ($validator->valid("title") and $validator->valid("text"))
Eu preciso ter a segunda declaração ($validator->valid("text")
) avaliados mesmo que o primeiro avalie como falso. Gostaria de perguntar se existe uma maneira fácil de forçar o PHP a avaliar sempre as duas declarações. Obrigada!
Solução
Isso é conhecido como Avaliação de curto -circuito, e para evitá -lo, você precisa fazer isso, usando um único &
:
if($validator->valid("title") & $validator->valid("text")) {
}
Observe que isso não está usando Operadores lógicos mas na verdade operadores bitwise:
Eles são operadores que atuam nas representações binárias dos números. Eles não tomam valores lógicos (ou seja, "verdadeiros" ou "falsos") como argumentos sem primeiro convertê -los nos números 1 e 0, respectivamente. Nem eles retornam valores lógicos, mas números. Claro, você pode tratar posteriormente esses números como se fossem valores lógicos (nesse caso 0 é lançado para "falso" e qualquer outra coisa é lançada para "verdadeiro"), mas isso é uma consequência das regras de elenco do tipo PHP, e nada a fazer com o comportamento dos operadores.
Como tal, existe algum debate sobre se é uma boa prática usar esse efeito colateral para contornar a avaliação de curto-circuito. Pessoalmente, eu pelo menos colocaria um comentário de que o & é intencional, mas se você quiser ser o mais puro possível, deve avaliar se eles são válidos primeiro e depois fazer o IF.
Outras dicas
$isValidTitle = $validator->valid("title");
$isValidText = $validator->valid("text");
if($isValidTitle && $isValidText)
{
...
}
Isso vai sear?
Tente avaliar cada termo separadamente:
$term1 = $validator->valid("title");
$term2 = $validator->valid("text");
if($term1 && $term2) {
//things to do
}
Esta pode não ser a melhor implementação, mas você sempre pode fazer:
$a=$validator->valid("title");
$b=$validator->valid("text");
if($a && $b) {...}
Você pode definir uma função como:
function logical_and($x,$y) {return ($x && $y);}
Como o PHP usa o valor de chamada por valor, isso funciona.
Como alternativa, se você puder modificar os instanciais do validador de classe $, poderá fazer com que o método válido aceite uma string ou uma matriz. Se for uma matriz, ele executa o código que já existe em cada item e retorna apenas true se todos os itens forem "válidos".