Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've just learnt how lazy evaluation works and I was wondering: why isn't lazy evaluation applied in every software currently produced? Why still using eager evaluation?

share|improve this question
    
Here's an example of what can happen if you mix mutable state and lazy evaluation. alicebobandmallory.com/articles/2011/01/01/… –  Jonas Elfström Mar 15 '13 at 9:08

4 Answers 4

up vote 12 down vote accepted

Lazy evaluation requires book-keeping overhead- you have to know if it's been evaluated yet and such things. Eager evaluation is always evaluated, so you don't have to know. This is especially true in concurrent contexts.

Secondly, it's trivial to convert eager evaluation into lazy evaluation by packaging it into a function object to be called later, if you so wish.

Thirdly, lazy evaluation implies a loss of control. What if I lazily evaluated reading a file from a disk? Or getting the time? That's not acceptable.

Eager evaluation can be more efficient and more controllable, and is trivially converted to lazy evaluation. Why would you want lazy evaluation?

share|improve this answer
2  
Lazily reading a file from disk is actually really neat--for most of my simple programs and scripts, Haskell's readFile is exactly what I need. Besides, converting from lazy to eager evaluation is just as trivial. –  Tikhon Jelvis Dec 12 '11 at 8:18

Mainly because lazy code and state can mix badly and cause some hard to find bugs. If the state of a dependent object changes the value of your lazy object can be wrong when evaluated. It's much better to have the programmer explicitly code the object to be lazy when he/she knows the situation is appropriate.

On a side note Haskell uses Lazy evaluation for everything. This is possible because it's a functional language and doesn't use state (except in a few exceptional circumstances where they are clearly marked)

share|improve this answer
    
Yeah, mutable state + lazy evaluation = death. I think the only points I lost on my SICP final were about using set! in a lazy Scheme interpreter. >:( –  Tikhon Jelvis Dec 12 '11 at 8:14

Lazy evaluation's is not always better.

The performance benefits of lazy evaluation can be great, but it is not hard to avoid most unnecessary evaluation in eager environments- surely lazy makes it easy and complete, but rarely is unnecessary evaluation in code a major problem.

The good thing about lazy evaluation is when it lets you write clearer code; getting the 10th prime by filtering an infinite natural numbers list and taking the 10th element of that list is one of the most concise and clear way of proceeding: (pseudocode)

let numbers = [1,2...]
fun is_prime x = all (map (y-> y mod x == 0) [1..x])
let primes = filter is_prime numbers
let tenth_prime = first (take primes 10)

I believe it would be quite difficult to express things so concisely without lazyness.

But lazyness isn't the answer to everything. For starters, lazyness cannot be applied transparently in the presence of state, and I believe statefulness cannot be automatically detected (unless you are working in say, Haskell, when state is quite explicit). So, in most languages, lazyness needs to be done manually, which makes things less clear and thus removes one of the big benefits of lazy eval.

Furthermore, lazyness has performance drawbacks, as it incurs a significant overhead of keeping non-evaluated expressions around; they use up storage and they are slower to work with than simple values. It is not uncommon to find out that you have to eager-ify code because the lazy version is dog slow- and it is sometimes hard to reason about performance.

As it tends to happen, there is no absolute best strategy. Lazy is great if you can write better code taking advantage of infinite data structures or other strategies it allows you to use, but eager can be easier to optimize.

share|improve this answer
    
+1 for the first and last paragraphs (-: –  Murph Dec 11 '11 at 22:29
    
Would it be possible for a really clever compiler to mitigate the overhead significantly. or even take advantage of laziness for extra optimizations? –  Tikhon Jelvis Dec 12 '11 at 8:20

As @DeadMG noted Lazy evaluation requires book-keeping overhead. This is expensive relative to eager evaluation. Consider this statement:

i = (243 * 414 + 6562 / 435.0 ) ^ 0.5 ** 3

This will take a bit of calculation to calculate. If I use lazy evaluation, then I need to check if it has been evaluated every time I use it. If this is inside a heavily used tight loop then the overhead increases significantly, but there is no benefit.

With eager evaluation and a decent compiler the formula is calculated at compile time. Most optimizers will move the assignment of any loops it occurs in if appropriate.

Lazy evaluation is best suited to loading data which will be infrequently accessed and has a high overhead to retrieve. It is therefore more appropriate to edge cases than core functionality.

In general it is good practice to evaluate things that are frequently accessed as early as possible. Lazy evaluation does not work with this practice. If you will always access something, all lazy evaluation will do is add overhead. The cost/benefit of using lazy evaluation decreases as the item being accessed becomes less likely to be accessed.

Alway using lazy evaluation also implies early optimization. This is a bad practice which often results in code which is much more complex and expensive that might otherwise be the case. Unfortunately, premature optimization often results in code that performs slower than simpler code. Until you can measure the effect of optimization, it is a bad idea to optimize your code.

Avoiding premature optimization does not conflict with good coding practices. If good practices were not applied, initial optimizations may consist of applying good coding practices such as moving calculations out of loops.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.