Where exactly does the LazyEvalutaion advantage appear?

In the last few days, I have been researching LazyEvaluation in terms of performance, mostly wondering where the LazyEvalutaion performance advantage comes from .

It was so incomprehensible to me that I read various articles, but very few, including

What are the benefits of lazy grading?

This means evaluating the syntax tree . If you evaluate the syntax tree lazily (that is, when the value that it represents is necessary), you should carry it through the previous steps of your calculations in its entirety. This is the overhead of lazy pricing. However, there are two advantages. 1) , you will not evacuate the tree unnecessarily if the result is never used ,

JavaScript, for example, implemented if syntax.

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

In this normal scenario, we have no performance issues.

For evaluation, performed, not evaluated, is ignored in the syntax tree.

However, in some recursive loop, the Tak function of the AKA Tarai function

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)); }

Since the Eager Evaluation JS strategy evaluates the inevitability of the function (arguments), the if-else control must not be evaluated anymore, and the number of evaluation steps of the tak function explodes.

Unlike this drawback of Eager Evaluation (JS or other languages), Haskell can evaluate tak without problems as it is, and some JS library such as lazy.js excels in a certain area, for example, functional programming that requires management recursive list.

Besides the endless list, I understand that this is the exact reason for LazyEvaluation's performance. Am I right?

+3
source share
1 answer

I think you have the right idea.

I don’t think you need all this complexity. Imagine JavaScript was

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

Now imagine that a veryExpensiveFunction implemented.

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

If JavaScript, because || lazy (only evaluates the second argument, if necessary), it will return very quickly (because true is, well, true!). If it were implemented instead

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

This will take some time to evaluate, because you overestimated the arguments. Now imagine the magic applied to || has been applied to every function (i.e. lazy language), and you can probably imagine what performance benefits laziness can bring.

In your example

 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)); } 

Imagine that everything was lazy.

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

It does nothing (nothing needs to be evaluated). a not used, so nothing is evaluated.

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

Now we can manage the tak score. Estimating how we need to get the results, we first substitute the values ​​in (we replace the variables with our arguments). Then we calculate the condition, and then only that side of the conditional that we need.

  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); 

In this example (assuming that I did not make any terrible typos), we do not need to evaluate anything other than arguments, and no recursive calls are made.

+3
source

Source: https://habr.com/ru/post/950882/


All Articles