3

在过去的几天里,我研究了LazyEvaluation,主要是在性能方面,想知道LazyEvalutaion的性能优势在哪里出现LazyEvalutaion的性能优势究竟在哪里出现?

这是这么不清楚我阅读各种文章,但极少数,包括

What are the advantages of Lazy Evaluation?

这是指语法树的评价。如果您懒惰地评估了语法树 (即需要它所代表的值),则您的 必须通过整个计算的上一步完成其 。这是懒惰评估的开销。但是,还有 两个优点。 1)你将不必evaulate树如果 结果是从未使用过

JavaScript中,例如,实施如果语法。

if(true) 
{ 
    //to evaluate 
} 
else 
{ 
    //not to evaluate 
} 

在这种普通的情况下,我们没有任何性能问题。

要评估完成,不进行评估,在语法树中将被忽略。

然而,在一些递归循环,例如,Tak function AKA Tarai function

函数德(X,Y,Z){ 返回(X < = Y)? y: tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y)); }

由于JS的渴望评估战略评估函数(参数)的必然性, 的如果 - 其他 - 不被评估控制不再有效,并且德功能爆炸的评估步骤的数目。

反对跃跃欲试评估(JS或其他语言)的这一缺点,哈斯克尔可以评估没有问题,因为它是,有些JS库如lazy.js胜过像函数式编程,其中递归列表中的特定区域需要管理。

除了无限的列表,我明白这是LazyEvaluation性能优势的确切原因。我对么?

+2

对于haskell程序员来说,性能实际上是懒惰评估中棘手的部分之一。真正的好处在于表达能力,允许程序员以多种不同的方式设计解决方案(例如,我想将这些代码表示为无限列表),并且能够将解决方案拆分为可轻松组成的部分,灵活在一个严格的语言评估问题将决定你如何构建你的代码。你也需要懒惰才能真正拥有一种“声明式”的语言,并且(理想情况下)一旦你拥有了你从未想过的“评估”。 – jberryman

+1

@jberryman,感谢您的输入。我同意。对于最后一部分,“声明式”,除了懒惰,我认为我们真的需要通过事件流以FRP方式将语言与IO结合起来。顺便说一下,我喜欢你网站上的照片。 –

回答

3

我认为你有正确的想法。

虽然我不认为你需要所有的复杂性。想象一下,JavaScript是

if (veryExpensiveFunction()) { 
    doThis(); 
} else { 
    doThat(); 
} 

现在想象一下veryExpensiveFunction已经实现。

function veryExpensiveFunction() { 
    return true || evenMoreExpensiveFunction(); 
} 

如果JavaScript的,因为||是懒惰的(仅限于评估是否需要第二个参数),这将返回速度非常快(因为true,没错,是真的!)。如果它被实施,而不是像

function veryExpensiveFunction() { 
    var a = true; 
    var b = evenMoreExpensiveFunction(); // forces the evaluation 

    return a || b; 
} 

这将需要年龄来评估,因为你已经不必要地评估参数。现在想象一下适用于||的魔法适用于每一种功能(即懒惰的语言),你可以想象懒惰可能带来的那种性能优势。

在您的例子

function tak(x,y,z){ return (x <= y) ? y : tak(tak(x-1, y, z), tak(y-1, z, x), tak(z-1, x, y)); } 

让我们想象一下,一切都懒。

var a = tak(1,2,3); 

这什么都不做(没什么需要评估)。没有使用a,所以没有评估。

var a = tak(1,2,3); 
console.log(a); 

现在我们有能力推动tak的评估。当我们需要得到结果时进行评估,我们首先将值替换(用它们的参数替换变量)。然后我们评估条件,然后评估我们需要的条件。

console.log((1 <= 2) ? 2 : tak(tak(1-1, 2, 3), tak(2-1, 1, 3), tak(3-1, 1, 2)); 
console.log( true ? 2 : tak(tak(1-1, 2, 3), tak(2-1, 1, 3), tak(3-1, 1, 2)); 
console.log(2); 

在这个例子中(假设我没有作出任何可怕的拼写错误),那么我们就需要评估任何东西比其他的参数也没有递归调用制成。

+0

谢谢@Jeff Foster。我没有注意到||目前为止很懒,所以非常翔实。然而,这种技术不能用于递归函数,因为我们已经有了通过(参数)来调用函数,并且它立即被计算出来,是正确的吗? –

+0

不可以。只根据需要进行评估。为了推动评估,有人必须要求递归函数的结果。 –

+0

嗯,这还不是很清楚。是否可以使用lazy ||写下tak函数的代码技术,如果你不介意。 –