为什么语言不能使用短路评估?

mar*_*cgg 39 language-agnostic conditional short-circuiting

为什么语言不能使用短路评估?不使用它有什么好处吗?

我看到它可能导致一些表演问题......这是真的吗?为什么?


相关问题:使用短路评估的好处

RBa*_*ung 40

不使用短路评估的原因:

  1. 因为如果你的函数,属性获取或操作符方法有副作用,它会表现不同并产生不同的结果.这可能与以下内容相冲突:A)语言标准,B)您的语言的先前版本,或C)典型用户的语言的默认假设.这些是VB不短路的原因.

  2. 因为您可能希望编译器可以自由地重新排序和修剪表达式,运算符和子表达式,而不是按照用户键入它们的顺序.这些是SQL不会短路的原因(或者至少不是大多数开发人员认为它会这样做的方式).因此,SQL(和其他一些语言)可能会短路,但只有当它决定并且不一定按照您隐式指定的顺序时.

我假设您在询问"自动,隐式特定于订单的短路",这是大多数开发人员对C,C++,C#,Java等的期望.BB和SQL都有办法明确强制特定于订单短路.然而,通常当人们提出这个问题时,这是一个"做我想要的"问题; 也就是说,它们的意思是"为什么它不能做我想要的?",就像在我写的顺序中自动短路一样.

  • @MarkJ:不,它不能.想想Java表达式`(thing == null || thing.getField()== 1)`. (2认同)
  • (续)说VB没有"暗示隐含或默认短路"就像说C#没有​​它,在任何一种情况下,它都是完全错误的.如果你在VB中的条件语句中使用`And`就会犯一个语义错误,就好像你在C#中的条件语句中使用`&`一样,编译器会相应地发出错误.所以Kibbee也是错的:VB也没有给你那个选择(除非你指的是'Option Strict`).逻辑运算和位运算之间存在明显的语义区别. (2认同)

Ben*_*n S 7

我能想到的一个好处是,某些操作可能会产生您可能会发生的副作用.

例:

if (true || someBooleanFunctionWithSideEffect()) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

但这通常不赞成.

  • 是的,这就是为什么我说我的例子不赞成. (4认同)
  • 这类似于superjoe30的答案(每次增量y).反对这个的论点是运行someBooleanFunctionWithSideEffect()并分配结果,以便稍后测试它.这样做更清晰,更容易阅读和理解正在发生的事情 (2认同)
  • 除非您希望`someBooleanFunctionWithSideEffect()`仅在第一个操作为false时执行其副作用. (2认同)

T.E*_*.D. 5

Ada默认不这样做.为了强制进行短路评估,您必须使用and thenor else代替andor.

问题在于,在某些情况下,它实际上会减慢速度.如果第二个条件快速计算,并且第一个条件对于"和"几乎总是为真,或者对于"或"则为假,那么额外的检查分支指令就是一种浪费.但是,据我所知,对于具有分支预测器的现代处理器,情况并非如此.另一个问题是,编译器可能碰巧知道第二一半是便宜还是可能失败,并且可能要相应地重新排序检查(这要是短路行为定义它不能做的).

我听到过反对意见,在第二次测试有副作用的情况下,它会导致代码的意外行为.恕我直言,如果你不太了解你的语言,它只是"意外",但有些人会争辩这一点.

如果您对实际语言设计者对此问题的看法感兴趣,请参阅Ada 83(原始语言)基本原理的摘录:

可以按任何顺序计算布尔表达式(如A和B)的操作数.根据术语B的复杂性,仅当术语A具有值TRUE时,才可能更有效(在一些但不是所有机器上)来评估B. 然而,这是编译器采取的优化决策,并且假设始终完成此优化是不正确的.在其他情况下,我们可能希望表达条件的组合,其中只有在满足先前条件时才应评估每个条件(具有意义).这两件事都可以通过短路控制形式来完成......

在Algol 60中,只能通过使用条件表达式来实现短路评估的效果,否则将执行完整的评估.这通常会导致构造变得乏味,无法遵循......

有几种语言没有定义如何评估布尔条件.因此,基于短路评估的程序将不可移植.这清楚地说明了将布尔运算符与短路控制形式分开的必要性.