所有的编程语言都有布尔短路评估吗?
在PHP代码中
if(a() && b())
当第一个操作数计算结果为false
, b()
将不会被评估。
同样,在
if (a() || b())
当第一个操作数的计算结果为true
, b()
将不会被评估。
对于Java,C#等所有语言来说都是如此吗?
这是我们使用的testing代码。
<?php function a(){ echo 'a'; return false; } function b(){ echo 'b'; return true; } if(a() && b()){ echo 'c'; } ?>
这就是所谓的短路评估 。
从C(C,C ++,Java,C#)派生的语言通常是正确的,但在所有语言中都不是这样。
例如,VB6不会这样做,也不会在早期版本的VB.NET中完成。 VB8(在Visual Studio 2005中) 为此引入了AndAlso和OrElse运算符。
另外,从评论看,csh似乎从右到左进行短路评估,使事情变得更加混乱。
还应该指出的是,短路评估(或缺乏)有其危险性要注意。 例如,如果第二个操作数是一个具有任何副作用的函数,那么该代码可能不会像程序员所期望的那样执行。
VB6不是这样的。
在VB.net中,如果您想要跳过评估第二个expression式,则必须使用“AndAlso”而不是“And”。
所有的语言,如JAVA,C#等,这是真的吗?
在C#中,这仅适用于短路操作符||
'和' &&
'; 如果你只是使用“ |
'或' &
'每次都会评估双方。
这就是所谓的短路评估 ,大多数语言都是这样做的。 在一些语言中存在不这样做的操作符。
帕斯卡的原始版本没有,导致了很多的悲伤。 现代帕斯卡,如delphi与C等人一样工作。
C:PHP,Java,C ++,C#等的“孩子”,或者像Perl一样的“灵感”中的语言也是如此。
但是对于VB来说这是不对的(至less在.NET之前,为此引入了新的关键字)。
(这真的令人不安第一次使用VB ^^)
Ada有特殊的短路forms的条件:
and then or else
像这样使用:
if p.next /= null and then p.next.name = 'foo' if x = 0 or else 1/x = y
从某种angular度来说,这种方式很好,因为你可以推断程序员知道expression式需要短路,条件不是偶然的。
Microsoft VBScript (通常与“经典”ASP一起使用)没有对布尔运算符进行短路评估,而是使用按位评估。 这是有史以来可能是最糟糕的语言的原因之一!
“VBScript不是逻辑的,VBScript是按位进行的,所有所谓的逻辑运算符都是在数字上工作,而不是在布尔值上运行,而且,或者,XOr,Eqv和Imp都将它们的参数转换为四字节整数,对整数中的每一对比特进行逻辑运算,并返回结果,如果True为-1,False为0,则所有的结果全部消失,因为-1的所有比特都打开,0的所有比特都打开但如果其他数字进入,所有投注都closures。
从这个博客采取。 由Eric Lippert。
对于Java也是如此,但运营商|,&等将评估双方。
在Delphi中它是一个编译器选项。
在Erlang, and
/ or
运营商不做短路评估; 如果你想要短路的话,你必须使用orelse
和其他操作符。
这被称为短路评估,除了VB,VB.NET和Fortran以外,所有使用过的语言(C,C ++,C#,Java,Smalltalk,Javascript,Lisp)都是常见的。
这实际上是一个非常有用的function。 没有短路,你将无法做到这一点:
if(a!= null && a.isBlank())
没有短路,你将不得不嵌套的if语句,因为如果一个为空的第二部分会抛出一个错误。
大多数语言(我所见过的)都使用CONDITIONAL运算符(如&&和||)进行短路评估。 只要其中一个条件满足要求,他们就会停止评估。 (&&上的第一个错误,||上的第一个错误)
所有BINARY运算符(如&和|)都将被处理。 (原版的)
所有BITWISE运算符(如&和|)都将被处理。 (编辑:5/10/17)
Coldfusion将自然做短循环评估。 我相信所有的CF开发者都写道:
<cfif isdefined("somevariable") and somevariable eq something> //do logic </cfif>
MATLAB是区分“标准” 逻辑运算符和短路 运算符的一种语言:
- &(AND运算符)和| (OR运算符)可以按照元素的方式对数组进行操作。
- &&和|| 是第二个操作数仅在结果没有完全由第一个操作数确定时求值的短路版本。 这些只能对标量进行操作,而不能对数组进行操作。
在标准的FORTRAN或Fortran中,布尔expression式的操作数可以按任何顺序求值。 不完整的评估是允许的,但实现定义。
这允许优化布尔expression式,如果严格的从左到右的顺序被强制执行,这是不允许的。 需要严格sorting的expression式必须分解成单独的条件语句,或者可以实现依赖于实现的假设。
由于分解用于强制sorting,因此单独的IF语句不能总是优化为单个expression式。 然而,短路评估是明确的分解,这从来没有比强制执行严格的从左到右sorting以允许懒惰评估的语言差。
源自FORTRAN(Fortran,BASIC,VBn)的语言和旨在实现类FORTRAN效率的语言(Pascal,Ada)最初遵循FORTRAN允许无序评估的例子。
其他答案已经给出了有和没有短路评估的语言的很好的例子,所以我不再重复。
只需添加一个有趣的点:像Clojure这样的Lisp具有布尔短路评估function,而且通过使用macros,可以非常简单地定义任何你喜欢的操作符,并通过短路评估。
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