惰性求值和短路求值有什么区别吗?

21

来自维基百科:

惰性求值是指:

在程序语言理论中,惰性求值或需求调用是一种评估策略,它延迟表达式的求值直到其值被需要时才进行

短路求值是指:

短路求值、最小求值或麦卡锡求值表示某些编程语言中某些布尔运算符的语义,其中第二个参数仅在第一个参数不足以确定表达式的值时才执行或计算

那么,举个例子,当我有:

if(false && true && true) {
    //boo
} 
据我所知,编译器不会执行false后面的表达式,因为我用了 && ,所以整个表达式最终会变成false。(对吗?)
那么这种行为叫做短路求值还是惰性求值呢?

你对于“解析”(parsing)的实际含义存在一些误解。 - Gumbo
@Gumbo 编辑,我认为 executing 是正确的单词,不是吗? - Afshin Mehrabani
1个回答

22

区别在于,在惰性求值的情况下,只有在需要时才对表达式进行求值,而在短路求值的情况下,表达式求值会在得到结果后立即停止。这是一种有些正交的概念。

惰性求值可以应用于任何计算(短路求值方案通常仅用于布尔值)。它不会削减无用的计算,但会延迟整个计算,直到需要其结果。

variable = bigAndSlowFunc() or evenSlowerFnc()
if (carry out heavy computations)
  print "Here it is: ", variable
else
  print "As you wish :-)"
如果评估是惰性的,variable 只会在我们选择进入第一个(then)分支的情况下计算,否则它不会被计算。 在评估阶段(当我们准备调用 print 的参数时),可以使用短路方案来决定是否需要调用 evenSlowerFnc
因此,在您的示例中,由于没有延迟计算,所以采用了短路评估。

实际上,使用惰性求值有时可以导致无用计算的截断。例如,在使用Django查询集时,您可以使用filter(或exclude)根据需要调整过滤条件:只有在访问结果时才会运行实际的SQL查询。 - Arseny
4
在惰性求值中,只有在需要其值时才会评估表达式。因此,如果不需要表达式的值,则不会对其进行评估。考虑f() && g(); 当需要这个表达式的值时,如果f()评估为true,则推迟计算g()的值直到需要为止。此外,只有在需要时才会计算g()的值。短路求值是惰性求值的一个简单情况。 - Theodore Norvell
在短路求值的情况下,g() 要么被计算,要么不被计算。它根本没有被延迟。好吧,直到 f() 完成,它才会执行,但是这种从左到右的执行方式是当我们写 f() && g() 时所期望的。 - Artem Sobolev
2
你重申了我的观点,即对于 g() 的评估将被延迟直到需要为止。这是惰性求值(对于右操作数)。这恰好发生在 f() 被评估为 true 之后,但又怎样呢?与 C 中的评估模型“按位与”不同的是 E&F,它会先评估 EF 然后再进行(按位)“与”运算。Java 有些不同,强制要求从左到右评估操作数,但又怎样呢?考虑 Haskell 预定义中 && 的定义 {True && x = x; False && _ = False}。这的行为与 C 的 && 完全相同,因为 Haskell 使用惰性求值。 - Theodore Norvell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接