短路评估何时不好?


12

为了更清楚一点,我声明我已经花了很多时间使用不同的语言。但是直到现在它要么一直使用它,要么根本不支持它。

现在,我可以从需要VB.net的项目开始工作,并且我看到它在ANDANDALSO方面提供了两种方式。第一个不会短路,第二个会短路。

因此,这使我想知道为什么?像这样进行设置似乎意味着人们经常想切换模式。但是我认为在任何情况下使用短路都是一件坏事。

我知道这很可能会涉及更多选项,因此,如果我需要将其放在其他地方,只需告诉我在哪里。

尽管我希望至少有一个正式的答案,但是关于为什么有两个选择总比总要做短路更好的原因。


2
SO上有很多重复之处:为什么一种语言不使用短路评估?
布朗

Answers:


5

逻辑表达式中的某些术语可能会产生副作用。有时有必要确保所有副作用均按规定的顺序发生,并且没有一个被跳过,而评估结果指导了该逻辑:

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

在其他情况下,如果先前的评估返回false,则您不希望评估其余的任何项。

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

有些人会/已经争论过,在第二个示例中依靠短路行为是不好的形式,但这已经进入了编码风格和信念体系。世界上有很多非常好的代码确实依赖于一种语言提供的几乎所有功能,而事实就是如此。

VB的ANDALSO很清晰,似乎是在使这种做法更容易接受。

正如JimmyJames在回答中指出的那样,短路评估可能会对性能产生可衡量的影响。不提供该机制的语言总是评估表达式的每个术语,而提供这种机制的语言则可以生成额外的分支语句。无论哪种方式,很大程度上取决于评估每个术语所需的处理步骤数量,还取决于编译器和CPU架构。您通常不会在意这些事情,除非您在代码中有了一个确定的瓶颈,并且需要研究如何缓解它。关于允许在代码中进行短路评估的任何有无规则,都有可能导致缓慢的代码和尽早优化的机会大致相等,可能会浪费时间,因此请务必先评估再优化。


4
尽管实际上是正确的,但这并不是一个很好的设计。
罗伯特·哈维

2
@RobertHarvey,我无法编写没有副作用的控制系统,并且如果我对结果没有反应,也无法正确控制该系统。换句话说,克服它;)。
jwdonahue

7
否,但是您可以将那些副作用函数的结果分配给布尔变量,检查if条件下的那些变量并仍然短路。在某些方面,我确实同意这是一种风格上的区别,但是它确实具有使事物变得清晰的优点。
罗伯特·哈维

3
@jwdonahue如果混淆的风险较低,可以使用“大词”。像这样的代码块出现混乱和丢失某些细微差别的风险非常高,并且可能对逻辑造成灾难性的影响。让阅读开发者很难思考永远都不是一件好事。
jpmc26

5
“逻辑表达式中的某些术语可能会产生副作用”-尽管此开场白是正确的,但我认为此答案未能指出依赖副作用是不好的。实际上,比依靠短路评估来防止虚假评估要糟糕得多。该答案确实暗示可能是错误的形式。
aroth

20

显然,您的问题不是关于短路总的来说是好是坏,而是关于VB.NET为什么为操作员提供和不提供短路。考虑到这一点,答案是

短路评估什么时候不好?

很简单:当它违反向后兼容性时

好的,现在您可以说VB.NET与旧的VB6或VBA不是很向后兼容,但是至少该语言的某些部分是向后兼容的。微软保留旧的AND和OR语义(不发生短路)的决定使得在将旧的VB程序移植到VB.NET时,不太可能发生大量错误。

另一方面,VB.NET语言设计人员可能与您分享了有关短路是一件好事的观点。当我没记错的时候,第一个VB.NET预发行版本为AND或OR运算符提供了短路,但是开发人员的反馈一定很糟糕,MS在VB.NET 1.0出现之前就撤回了这一决定。因此,设计人员决定根据新关键字ANDALSOORELSE在向后兼容性和实用性之间进行权衡取舍来实现它。

恕我直言,这是一个很好的决定。在过去的十年中,我不得不移植一些较旧的程序,而不必对每个逻辑表达式(包括AND和/或OR(双关语))进行大量的影响分析,从而使该任务变得更加轻松和经济。另一方面,每当我不得不在VB.NET中编写新的逻辑表达式时,我对运算符的默认选择是短路形式,这是我习惯于C,C ++,C#等的形式,并且它允许我以更简洁的形式写一些成语(即使ANDALSO还要多输入4个字符)。

如果您不相信,我建议阅读Joel Spolsky关于Martian Headsets的精彩文章,这是为什么在所涉及的组件或语言或API达到一定规模的用户群后,为什么不能轻易撤销软件开发中的早期设计决策的原因。


好的,这符合资格,与火星耳机的链接似乎一点也不相关。
jwdonahue

6
@jwdonahue:我不知道你为什么认为这是一头胡话,恰恰相反。关于火星耳机的文章是关于为什么在数十年前做出的软件开发中的某些设计决策在所涉及的组件或语言或API达到一定规模的用户群后,无法轻易撤销的。这样的类比真的很难理解吗?VB6 在过去非常流行,我敢肯定,全世界仍有数十万家公司在VB6或VBA中运行关键任务应用程序。
布朗

我不太了解“火星人头号”一词的真实含义。确保X和Y(例如,螺母和螺栓)之间的互操作性的必要条件是对X和Y分别制定标准,以使最坏情况的螺母将容纳比规定的略差的螺栓,反之亦然。为了避免使螺母或螺栓变得不必要的昂贵,或者在螺母和螺栓之间没有不必要的倾斜,人们应该尝试编写规格,但是分开指定两个半部可以确保比试图制定一个规格更可靠的互操作性。服务双方。
超级猫

3
@supercat:这是关于已经存在和使用了数万亿个螺母(或VB6代码行)的情况,现在,螺栓(或本例中的VB编译器)将被新一代的螺母代替。如果现有螺母仅适合非公制螺栓,则仅使新的公制螺栓不经济。
布朗

tl; dr:VB是BASIC(始于1964年的一种语言)的方言,在BASIC中,该And操作不会短路,SQL(1974),FORTRAN(1956)或Pascal(1970)都不短路。

3

短路评估什么时候不好?

一旦您开始依赖期望在布尔型总体结果的评估中执行的表达式的副作用,它们就会变得很糟糕


1

警告:这有点神秘,因为在几乎所有情况下,开发人员都不必担心。但是...由于条件评估会导致性能下降,因为它会在执行中创建分支。非短路操作不会分支,更容易预测。

这种情况很少发生的原因是,成本通常很小,而且通常也比评估第二(或第三等)条件的成本要高。这仅在需要高性能的情况下才在计算昂贵的例程中起作用,然后也可能无关紧要。


我认为到目前为止,您只能优化逻辑语句,最终您必须进行分支。
jwdonahue

@jwdonahue我不明白你的意思。抱歉。
JimmyJames

我们在这里谈论组合逻辑。是否进行短路评估,您有一个或多个条件必须根据前一个条件的结果进行评估。因此,涉及分支。
jwdonahue

1
@jwdonahue当然,但是每个短路都是一个额外的分支。在某些情况下,例如,执行第二个表达式比执行第二个表达式之前检查第一个表达式的结果要快,即使第二个表达式通常无关紧要。同样,这很少重要。有人为此而向我提出的案例是用于矩阵乘法之类的事情,您需要进行许多简单的评估。
JimmyJames

1
我用您的信用更新了我的答案。
jwdonahue

0

Pascal并未定义AND和OR是否使用短路评估,这让您两全其美。

C和C ++具有按位运算符&和| 实际上,这可以为您提供非短路操作。如果没有明显的不同,编译器可以自由评估他们喜欢的任何方式。


@Deduplicator:如前所述,Pascal 没有定义 AND / OR是否使用短路评估。那意味着“不知道”。
超级猫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.