Fazer todas as linguagens de programação têm curto-circuito avaliação boolean?
-
22-07-2019 - |
Pergunta
No código PHP
if(a() && b())
quando as primeiras avalia operando para false
, b()
não serão avaliadas.
Da mesma forma, no
if (a() || b())
quando as primeiras avalia operando para true
, b()
não serão avaliadas ..
Isso é verdade para todas as línguas, como Java, C #, etc?
Este é o código de teste que usamos.
<?php
function a(){
echo 'a';
return false;
}
function b(){
echo 'b';
return true;
}
if(a() && b()){
echo 'c';
}
?>
Solução
Isso é chamado curto-circuito avaliação .
É geralmente verdade para linguagens derivadas de C (C, C ++, Java, C #), mas não é verdade para todos os idiomas.
Por exemplo, VB6 não faz isso, nem foi feito em versões anteriores do VB.NET. VB8 (no Visual Studio 2005) introduziu o AndAlso e OrElse operadores para esta finalidade.
Além disso, a partir dos comentários, parece que a avaliação realiza csh curto-circuito da direita para a esquerda, para tornar as coisas ainda mais confusas.
Também deve ser salientado que a avaliação curto-circuito (ou falta de) tem os seus perigos para estar ciente. Por exemplo, se o segundo operando é uma função que tem quaisquer efeitos secundários, em seguida, o código pode não funcionar exatamente como o programador pretendia.
Outras dicas
Não é verdade para VB6.
Em VB.net você tem que usar "AndAlso" em vez de "E" se você quer que ele pule avaliar a segunda expressão.
Isso é verdade para todas as línguas, como Java, C #, etc?
Em C este # só é verdade para os operadores '||
' e '&&
'-circuito curto; se você usar apenas '|
' ou '&
' que irá avaliar ambos os lados de cada vez.
É chamado curto-circuito avaliação e a maioria das linguagens fazer isso. Em algumas línguas, existe operadores que não fazer isso.
A versão original do Pascal não fez, o que causou muita dor. Pascais modernas, tais como o trabalho de Delphi da mesma maneira como C et al.
Ada tem formas de condicionais especiais circuito-curto:
and then
or else
usado como este:
if p.next /= null and then p.next.name = 'foo'
if x = 0 or else 1/x = y
Em alguns aspectos, é uma espécie de bom porque você pode deduzir que o programador conhecia a expressão precisava estar em curto-circuito e que a condicional não está funcionando por acidente.
É verdade para as línguas que são "filhos" do C:. PHP, Java, C ++, C #, ... ou no mesmo "inspiração", como Perl
Mas isso não é verdade para VB (pelo menos antes NET, que introduziu novas palavras-chave para isso).
(E isso é realmente preocupante o primeiro você trabalha com VB ^^)
Microsoft VBScript (muitas vezes utilizados em conjunto com ASP 'Classic') não teve avaliação de curto-circuito para operadores booleanos, em vez disso, usa avaliação bit a bit. Que é uma das muitas razões por que é possivelmente o pior linguagem de sempre!
"O que está acontecendo é que VBScript é não é lógico. VBScript é bit a bit. Tudo o chamado operadores lógicos trabalho em números, não em valores booleanos! Não, E, OR, XOR, Eqv e Imp todos converter os seus argumentos para quatro bytes inteiros, fazer a operação lógica em cada par de bits nos números inteiros, e retornar o resultado. Se é verdadeiro -1 e Falso é 0, em seguida, tudo funciona, porque-1 tem todos os seus bits ligado e 0 tem todos seus bits desligado. Mas se outros números de chegar lá, todos as apostas estão fora".
este blog. por Eric Lippert.
Em Delphi é uma opção de compilador.
Isto é verdade para Java tão bem, mas os operadores |., & Etc irá avaliar ambos os lados
Em Erlang, os operadores and
e or
não fazer avaliação de curto-circuito; você tem que usar operadores orelse
e andalso
se você quer um comportamento de curto-circuito.
em Fortran padrão ou Fortran, os operandos de uma expressão booleana pode ser avaliada por qualquer ordem. avaliação incompleta é permitido, mas a implementação definida.
Isso permite a otimização de expressões booleanas que não seriam permitidas caso rigorosa ordenação Esquerda para a Direita foi cumprida. Expressões que exigem ordenação estrita deve ser decomposto em condicionais separadas, ou suposições dependente de implementação pode ser feita.
Uma vez que a decomposição é usado para fazer cumprir a encomenda, segue-se que separado IF nem sempre pode ser otimizado em uma única expressão. No entanto, a avaliação de curto-circuito é explícita com decomposição, e isso nunca é pior do que línguas que impor estrito da esquerda para a direita ordenação para permitir a avaliação preguiçosa.
línguas wich são derivados de Fortran (Fortran, BASIC, VBN), e idiomas que foram concebidas para alcançar Fortran semelhante eficiência (Pascal, Ada) inicialmente seguido do exemplo Fortran de permitir fora de ordem de avaliação.
A maioria das línguas (todas as que eu já vi) usar a avaliação curto-circuito na operadores condicionais, como && e ||. Eles vão parar de avaliar, logo que uma das condições satisfez a exigência. (A primeira falsas sobre &&. O primeiro verdadeiro em ||)
operadores Todos os binários como & e |, são processados. (Original)
operadores All bit a bit como & e |, são processados. (Edit: 5/10/17)
Isso é chamado de avaliação de curto-circuito e é comum para todas as línguas que eu já trabalhei em (C, C ++, C #, Java, Smalltalk, Javascript, Lisp), exceto para VB, VB.NET e Fortran.
É realmente um recurso muito útil. Sem curto-circuito, você não seria capaz de fazer isso:
if (a != null && a.isBlank())
Sem um curto-circuito, você teria que ter aninhados if porque a segunda parte iria lançar um erro se uma era nulo.
Coldfusion vai nativamente fazer avaliação de curto circut. Estou certo de que todos os desenvolvedores CF ter escrito:
<cfif isdefined("somevariable") and somevariable eq something>
//do logic
</cfif>
MATLAB é uma linguagem que distingue entre "padrão" lógica operadores operadores e curto-circuito :
- & (operador AND) e | (OR operador) pode operar em matrizes de forma elemento-wise.
- && e || são versões de curto-circuito para que o segundo operando é avaliado apenas quando o resultado não é totalmente determinada pelo primeiro operando. Estes só podem operar em escalares , não matrizes.
Outras respostas têm dado bons exemplos de idiomas com e sem avaliação de curto-circuito por isso não vou repeti-los.
Apenas um ponto interessante para acrescentar: Lisps como Clojure têm avaliação boolean curto-circuito, mas, além disso você pode muito trivialmente definir qualquer operador você gosta com a avaliação curto-circuito através do uso de macros <. / p>
Exemplo de uma operação de "ne" curto-circuito em Clojure:
(defmacro nand
([x]
`(not ~x))
([x & xs]
`(let [nand# (not ~x)]
(if nand#
true ; short circuit if we can prove the nand is true
(nand ~@xs))))) ; continue with the other expressions otherwise
(nand true true)
=> false
(nand false (println "Expression with a side effect!"))
=> true