Quando a avaliação de curto-circuito é ruim?

12

Para ser um pouco mais claro, afirmo que passei muito tempo com idiomas diferentes. Mas até agora, tem sido, ou será usado o tempo todo ou não será compatível.

Agora, o trabalho me iniciou em projetos que exigem o VB.net, e vejo que ele fornece as duas maneiras em termos de AND e ANDALSO . O primeiro não provoca um curto-circuito e o segundo não.

Então isso me leva a pensar por quê? Como configurá-lo assim parece implicar que surgiria com bastante frequência que alguém desejaria mudar de modo. Mas não consigo pensar em nenhuma situação em que seria ruim usar o Short Circuit .

Eu sei que isso poderia muito bem se tornar mais uma opção, então se eu precisar colocar isso em algum outro lugar, diga-me onde.

Embora eu esteja esperando que haja pelo menos uma resposta oficial, por que ter as duas opções seria melhor do que sempre fazer um curto-circuito , quando disponível.

Kit Ramos
fonte

Respostas:

5

Alguns termos em uma expressão lógica podem ter efeitos colaterais. Às vezes, é necessário garantir que todos os efeitos colaterais ocorram na ordem estabelecida e que nenhum seja ignorado, e é o resultado da avaliação que guia a lógica:

if not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Em outros casos, você não deseja avaliar nenhum dos termos restantes se uma avaliação anterior retornar falsa.

if IsAirborne() and not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Alguns argumentaram que confiar no comportamento de curto-circuito no segundo exemplo é uma forma ruim, mas isso está entrando no estilo de codificação e nos sistemas de crenças. Existem muitos bits muito bons de código no mundo que dependem de quase todos os recursos que uma linguagem fornece, e é exatamente assim.

O ANDALSO da VB é preciso e parece ser uma tentativa de tornar a prática mais aceitável.

Como JimmyJames aponta em sua resposta, pode haver implicações mensuráveis ​​de desempenho em torno da avaliação de curto-circuito. Os idiomas que não fornecem o mecanismo, sempre avaliam todos os termos da expressão, enquanto os que o fornecem, podem gerar instruções de ramificação extras. De qualquer forma, depende muito do número de etapas de processamento necessárias para avaliar cada um dos termos e também das arquiteturas do compilador e da CPU. Normalmente, você não se importaria com essas coisas até ter um gargalo medido no código e precisar descobrir como aliviá-lo. Qualquer regra de "faça ou não" em relação à permissão de avaliação de curto-circuito em seu código teria uma chance praticamente igual de causar código mais lento e otimizar antecipadamente pode ser uma perda total de tempo; portanto, sempre meça e otimize.

jwdonahue
fonte
4
Embora factualmente correto, não é um ótimo design.
Robert Harvey
2
@RobertHarvey, não consigo escrever um sistema de controle que não tenha efeitos colaterais e não consigo controlar o sistema corretamente se não reagir aos resultados. Em outras palavras, supere isso;).
Jwdonahue 30/05
7
Não, mas você pode atribuir os resultados dessas funções de efeito colateral a variáveis ​​booleanas, verificar essas variáveis ​​em sua ifcondição e ainda causar um curto-circuito. Concordo que é, de certa forma, uma distinção estilística, mas tem a virtude de tornar as coisas claras.
Robert Harvey
3
@jwdonahue Não há problema em usar "grandes palavras" se o risco de confusão for baixo. O risco de confusão e falta de nuances específicas de um bloco de código como esse é extremamente alto e pode ser catastrófico para a lógica. Nunca é bom fazer o desenvolvedor de leitura pensar muito.
Jpmc26
5
"Alguns termos em uma expressão lógica podem ter efeitos colaterais" - Embora essa declaração de abertura esteja correta, sinto que essa resposta falha ao não apontar que confiar nos efeitos colaterais é ruim . Muito pior, na verdade, do que confiar na avaliação de curto-circuito para evitar avaliações espúrias. O que esta resposta sugere pode estar em má forma.
Aroth 31/05/19
20

Aparentemente, sua pergunta não é sobre o curto-circuito ser bom ou ruim em geral, mas sobre por que o VB.NET fornece aos operadores com e sem isso. Com isso em mente, a resposta para

quando é ruim a avaliação de curto-circuito?

é simplesmente: quando viola a compatibilidade com versões anteriores .

Ok, agora você pode dizer que o VB.NET não é muito compatível com o VB6 ou VBA antigo, no entanto, pelo menos algumas partes do idioma são. A decisão da Microsoft de manter a antiga semântica AND e OR (sem curto-circuito) reduziu a probabilidade de ocorrer uma categoria enorme de erros ao transportar programas VB antigos para o VB.NET.

Por outro lado, os designers de linguagem do VB.NET provavelmente compartilharam sua opinião sobre o curto-circuito ser uma coisa boa. Quando me lembro corretamente, as primeiras versões de pré-lançamento do VB.NET forneceram aos operadores AND ou OR um curto-circuito, mas o feedback do desenvolvedor deve ter sido tão ruim que a Microsoft retirou essa decisão antes que o VB.NET 1.0 aparecesse. Assim, os designers decidiram implementá-lo em termos de novas palavras ANDALSO- chave e ORELSEcomo uma troca entre compatibilidade e utilidade anteriores.

IMHO esta foi uma boa decisão. Eu tive que portar vários programas mais antigos na última década, e não ter que fazer uma análise de impacto pesado para todas as expressões lógicas, incluindo AND e / ou OR (trocadilhos), tornaram essa tarefa muito mais fácil e econômica. Por outro lado, sempre que tenho que escrever uma nova expressão lógica no VB.NET, minha opção padrão para os operadores são as formas de curto-circuito, é com isso que estou acostumado a partir de C, C ++, C # etc., e isso permite para escrever vários idiomas de forma mais concisa (mesmo que o ANDALSO precise de mais 4 caracteres para digitar).

Se você não está convencido, recomendo ler o excelente artigo de Joel Spolsky sobre os fones de ouvido marcianos , que explica por que as decisões iniciais de design no desenvolvimento de software não podem ser facilmente revogadas depois que o componente, idioma ou API em jogo alcançou uma base de usuários de um determinado tamanho .

Doc Brown
fonte
Ok, isso se qualifica como um discurso retórico e o link para os fones de ouvido marcianos não parece estar relacionado.
Jwdonahue 30/05
6
@jwdonahue: Eu não tenho idéia do porquê você acha que isso é um discurso retórico, pelo contrário. E o artigo sobre Martian Headsets é sobre o motivo pelo qual algumas decisões de design no desenvolvimento de software tomadas há várias décadas atrás não podem ser facilmente revogadas depois que o componente ou idioma ou API em jogo atingiu uma base de usuários de um determinado tamanho. A analogia não é realmente tão difícil de entender? O VB6 era muito popular no passado e, com certeza, ainda centenas de milhares de empresas no mundo têm aplicativos de missão crítica em execução no VB6 ou no VBA.
Doc Brown
Não vejo bem como o artigo "cabeçalhos marcianos" realmente se encaixa. O necessário para garantir a interoperabilidade entre X e Y (por exemplo, porcas e parafusos) é ter padrões separados para X e Y, de modo que uma porca de pior caso acomode um parafuso um pouco pior que o especificado e vice-versa. Deve-se tentar escrever as especificações para evitar tornar desnecessárias as porcas ou parafusos, ou ter uma quantidade desnecessária de despejo entre as porcas e os parafusos, mas especificar as duas metades separadamente torna possível garantir a interoperabilidade com muito mais confiabilidade do que tentar obter uma especificação. servir os dois lados.
Supercat
3
@ supercat: trata-se de já ter trilhões de porcas (ou linhas de código VB6) existentes e em uso, e agora os parafusos (ou neste caso o compilador VB) serão substituídos por uma geração mais nova. Se as porcas existentes se ajustarem apenas a parafusos não métricos, não é econômico fabricar apenas os novos sistemas métricos dos parafusos.
Doc Brown
tl; dr: VB é um dialeto do BASIC, uma linguagem que data de 1964, e no BASIC a Andoperação não provoca um curto-circuito, nem no SQL (1974), nem no FORTRAN (1956), nem no Pascal (1970).
Ben
3

quando é que a avaliação de curto-circuito é ruim?

Eles ficam ruins , assim que você começa a contar com os efeitos colaterais das expressões que espera executar na avaliação de um resultado geral booleano.

πάντα ῥεῖ
fonte
1

Advertência : Isso é um pouco esotérico, pois em quase todos os casos, os desenvolvedores não devem se preocupar com isso. Mas ... pode haver um impacto no desempenho devido à avaliação condicional, pois cria ramificação na execução. Uma operação sem curto-circuito não se ramifica e é mais previsível.

A razão pela qual isso raramente importa é que o custo geralmente é pequeno e também geralmente supera o custo da avaliação da segunda (ou terceira) condição. Isso só será importante em rotinas computacionalmente caras quando for necessário alto desempenho e ainda não será importante.

JimmyJames
fonte
Eu acho que você só pode otimizar uma afirmação lógica até o momento; eventualmente, você precisa tomar ramificações.
Jwdonahue 30/05
@jwdonahue Eu não entendo o seu ponto. Desculpe.
JimmyJames
Estamos falando de lógica combinatória aqui. Avaliação de curto-circuito ou não, você tem um ou mais termos que devem ser avaliados, dependendo do resultado de um período anterior. Portanto, a ramificação está envolvida.
Jwdonahue 30/05
1
@jwdonahue É claro, mas todo curto-circuito é um ramo adicional. Em certos cenários, a execução de duas expressões (por exemplo) é mais rápida do que a verificação do resultado da primeira antes da execução da segunda, mesmo que geralmente a segunda seja irrelevante. Novamente, isso raramente é importante. O caso que alguém me fez para isso foi para coisas como multiplicação de matrizes, nas quais você tem muitas avaliações simples.
JimmyJames 30/05
1
Atualizei minha resposta com crédito para você.
Jwdonahue 30/05
0

Pascal não definiu se AND e OR usam ou não a avaliação de curto-circuito, oferecendo o pior dos dois mundos.

C e C ++ têm operações bit a bit & e | que na prática oferecem operações sem curto-circuito. E os compiladores são livres para avaliar como quiserem, se isso não fizer uma diferença observável.

gnasher729
fonte
@ Reduplicador: Como observado, Pascal não definiu se o AND / OR usaria a avaliação de curto-circuito. Isso significa "não saber".
Supercat