Все ли языки программирования имеют логическую оценку короткого замыкания?

в PHP коде

if(a() && b())

когда первый операнд равен false, b() не будет оцениваться.

аналогично, в

if (a() || b())

когда первый операнд равен true, b() не будет оцениваться..

это верно для всех языков, таких как Java, C# и т. д.?

это тестовый код, который мы использовали.

<?php
function a(){
echo 'a';
return false;
}

function b(){
echo 'b';
return true;
}


if(a() && b()){
echo 'c';
}
?>

17 ответов


Это называется оценка короткого замыкания.

это обычно верно для языков, производных от C (C, C++, Java, C#), но не верно для всех языков.

например, VB6 этого не делает, и это не было сделано в ранних версиях VB.NET - ... VB8 (в Visual studio 2005) представил атакже и иначе операторов для этой цели.

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

следует также отметить, что оценка короткого замыкания (или отсутствие) имеет свои опасности, о которых следует знать. Например, если второй операнд-это функция, имеющая какие-либо побочные эффекты, то код может работать не совсем так, как предполагал программист.


Это не верно для VB6.

In VB.net вы должны использовать "AndAlso" вместо "И", если хотите пропустить оценку второго выражения.


Это верно для всех языков, таких как JAVA, C# и т. д.?

в C# это справедливо только для операторов короткого замыкания||' и '&&'; Если вы просто использовать '|' или '& - это будет оценивать обе стороны каждый раз.


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


в оригинальной версии Паскаль не сделал, что вызвало много горя. Современные Паскали, такие как Delphi, работают так же, как C et al.


Ada имеет специальные короткозамкнутые формы условных обозначений:

and then
or else

использовать так:

if p.next /= null and then p.next.name = 'foo'
if x = 0 or else 1/x = y

Это верно для языков, которые являются "детьми" C : PHP, Java, C++, C#, ... или в том же "вдохновении", как Perl.

но это не верно для VB (по крайней мере, до .NET, который ввел новые ключевые слова для этого).
(и это действительно беспокоит первый вы работаете с VB ^^ )


Microsoft VBScript (часто используется в сочетании с "классическим" ASP) не имел оценки короткого замыкания для булевых операторов, вместо этого он использует побитовую оценку. Что является одной из многих причин, почему это, возможно, худший язык когда-либо!

" Что происходит, так это то, что VBScript не логично. VBScript является побитовым. Все так называемые логические операторы работают на числах, а не на булевых значениях! Нет, и, или, XOr, Eqv и Imp все преобразовать их аргументы для четырехбайтовых целые числа, выполните логическую операцию на каждая пара битов в целых числах, и возвращать результат. Если True равно -1 и False равно 0, тогда все работает, потому что у -1 все его биты включены и 0 отключил все свои биты. Но если другие номера туда ставки сделаны".

принято от этот блог. Эрик Липперт.


в Delphi это опция компилятора.


Это верно и для Java, но операторы|, & etc будут оценивать обе стороны.


на Erlang, то and и or операторы не делают оценку короткого замыкания; вы должны использовать orelse и andalso операторы, если вы хотите короткое замыкание поведение.


большинство языков (все, что я видел) используют оценку короткого замыкания на условных операторах, таких как && и ||. Они прекратят оценку, как только одно из условий удовлетворит требование. (Первый false на &&. Первая правда на|/)

обрабатываются все двоичные операторы, такие как & и|. (Оригинал)

обрабатываются все побитовые операторы, такие как & и|. (Edit: 5/10/17)


это называется оценкой короткого замыкания, и это распространено для всех языков, на которых я когда-либо работал (C, C++, C#, Java, Smalltalk, Javascript, Lisp), за исключением VB, VB.NET и Фортран.

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

if (a != null && a.isBlank())

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


Coldfusion изначально будет выполнять оценку короткого замыкания. Я уверен, что все разработчики CF написали:

<cfif isdefined("somevariable") and somevariable eq something>
//do logic
</cfif>

MATLAB-это один язык, который отличает "стандартный"логические операторы и операторы короткого замыкания:

  • & (и оператор) и / (или оператор)могут работать с массивами по элементам.
  • && и | / являются версиями короткого замыкания, для которых второй операнд оценивается только тогда, когда результат не полностью определяется первым операндом. Они могут работать только на скаляры, не матрицы.

в стандартном FORTRAN или Fortran операнды логического выражения могут быть вычислены в любом порядке. Допускается неполная оценка, но реализация определена.

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

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

языки, производные от FORTRAN (Fortran, BASIC, VBn), и языки, которые были разработаны для достижения FORTRAN-подобной эффективности (Pascal, Ada), первоначально следовали примеру FORTRAN разрешая порядку оценки.


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

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

пример операции короткого замыкания "nand" в 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