所有编程语言都有布尔短路评估吗?

时间:2009-08-05 11:16:27

标签: language-agnostic if-statement short-circuiting

在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 个答案:

答案 0 :(得分:65)

这称为short-circuit evaluation

对于从C(C,C ++,Java,C#)派生的语言通常都是如此,但对于所有语言都不是这样。

例如,VB6没有这样做,也没有在早期版本的VB.NET中完成。 VB8(在Visual Studio 2005中)为此目的引入了AndAlsoOrElse运算符。

此外,根据评论,似乎csh从右到左进行短路评估,使问题更加令人困惑。

还应该指出,短路评估(或缺乏)有危险需要注意。例如,如果第二个操作数是一个具有任何副作用的函数,那么代码可能无法完全按照程序员的意图执行。

答案 1 :(得分:20)

VB6不是这样。

在VB.net中,如果你想让它跳过评估第二个表达式,你必须使用“AndAlso”而不是“And”。

答案 2 :(得分:14)

  

这适用于所有语言,例如JAVA,C#等吗?

在C#中,这仅适用于短路运算符“||”和“&&”;如果您只使用“|”或“&”,则每次都会对双方进行评估。

答案 3 :(得分:12)

它被称为short-circuit evaluation,大多数语言都这样做。在某些语言中,存在不执行此操作的运算符。

答案 4 :(得分:8)

Pascal的原始版本没有,这引起了很多悲伤。现代帕斯卡,如德尔福的工作方式与C等人一样。

答案 5 :(得分:7)

Ada有特殊的短路条件:

and then
or else

像这样使用:

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

在某些方面它有点好,因为你可以推断程序员知道需要短路的表达式,并且条件不会偶然发生。

答案 6 :(得分:5)

对于C语言的“孩子”语言来说确实如此:PHP,Java,C ++,C#,......或者像Perl一样的“灵感”。

但对于VB来说却不是这样(至少在.NET之前引入了新的关键字)。
(这真的令人不安第一次使用VB ^^)

答案 7 :(得分:4)

Microsoft VBScript(通常与'Classic'ASP一起使用)没有布尔运算符的短路评估,而是使用按位求值。这是有史以来可能是最糟糕的语言的众多原因之一!

  

“VBScript是怎么回事?   不符合逻辑。 VBScript是按位的。所有   所谓的逻辑运算符起作用   数字上,而不是布尔值!   不,和,或者,XOr,Eqv和Imp all   将他们的参数转换为四字节   整数,进行逻辑运算   整数中的每一对位,和   返回结果。如果True是-1并且   假是0然后一切都解决了,   因为-1的所有位都打开了   并且0的所有位都被关闭。但   如果其他数字进入那里,全部   投注结束了。“

摘自Eric Lippert的this blog.

答案 8 :(得分:3)

在Delphi中,它是一个编译器选项。

答案 9 :(得分:2)

对于Java也是如此,但运营商|,&amp;等会评估双方。

答案 10 :(得分:2)

这被称为短路评估,除了VB,VB.NET和Fortran之外,我曾经使用过的所有语言(C,C ++,C#,Java,Smalltalk,Javascript,Lisp)都很常见。

这实际上是一个非常有用的功能。如果没有短路,你将无法做到这一点:

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

如果没有短路,则必须使用嵌套的if语句,因为如果a为null,则第二部分会抛出错误。

答案 11 :(得分:2)

大多数语言(我所见过的所有语言)都使用CONDITIONAL运算符进行短路评估,例如&amp;&amp;和||。一旦其中一个条件满足要求,他们将停止评估。 (第一个假的&amp;&amp;。第一个真的在||)

所有BINARY运营商,如&amp;和|,被处理。 (原始)

所有BITWISE运营商,如&amp;和|,被处理。 (编辑:5/10/17)

答案 12 :(得分:2)

在Erlang中,andor运算符不进行短路评估;如果您想要短路行为,则必须使用orelseandalso运算符。

答案 13 :(得分:2)

在标准FORTRAN或Fortran中,可以按任何顺序计算布尔表达式的操作数。允许进行不完整的评估,但确定了实施。

这允许优化布尔表达式,如果强制执行严格的从左到右排序则不允许这样做。需要严格排序的表达式必须分解为单独的条件,或者可以依赖于实现的假设。

由于分解用于强制排序,因此不能始终将单独的IF语句优化为单个表达式。但是,短路评估在分解时是明确的,这绝不会比强制执行严格的从左到右排序以允许延迟评估的语言更糟糕。

源自FORTRAN(Fortran,BASIC,VBn)的语言,以及旨在实现类似FORTRAN效率的语言(Pascal,Ada)最初遵循允许无序评估的FORTRAN示例。

答案 14 :(得分:1)

Coldfusion本身会进行短期评估。我相信所有CF开发人员都写过:

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

答案 15 :(得分:1)

MATLAB是一种区分“标准”logical operatorsshort-circuit operators的语言:

  • &安培; (AND运算符)和| (OR运算符)可以以元素方式对数组进行操作。
  • &安培;&安培;和||是短路版本,仅当第一个操作数未完全确定结果时才评估第二个操作数。这些只能在标量上运行,而不能在阵列上运行。

答案 16 :(得分:0)

其他答案给出了有短期评估和没有短路评估的语言的好例子,所以我不再重复。

只需要添加一个有趣的观点:像Clojure这样的Lisp具有布尔短路评估,但是通过使用宏,您可以通过短路评估轻松定义任何运算符。< / p>

Clojure中短路“nand”操作的示例:

(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