Comparing lazy and eager evaluation
One way to compare lazy and eager evaluation is to look at how they handle function calls, conditional expressions, and infinite data structures. For example, consider the following pseudo-code:
if f(3) > 4 then g(5) else g(6)
In a lazy language, the function f(3) is not evaluated until it is compared to 4, and the function g(5) or g(6) is not evaluated until the if condition is resolved. This means that only one of the functions g will be executed, and the output will be either "f g" or "f". In an eager language, the function f(3) is evaluated as soon as it is encountered, and both functions g(5) and g(6) are evaluated before the if condition is checked. This means that both functions g will be executed, and the output will be "f g g".
Similarly, in a lazy language, an infinite data structure such as a stream or a generator can be created and manipulated without causing a memory overflow or a runtime error. For example, consider the following pseudo-code:
if n == 0 then [] else head(s) : take(n - 1, tail(s))
print(take(5, stream(1)))
In a lazy language, the function stream(1) is not evaluated until its elements are requested by the function take(5, stream(1)). This means that only the first five elements of the stream are computed and printed, and the output will be "[1, 2, 3, 4, 5]". In an eager language, the function stream(1) is evaluated as soon as it is encountered, and the function take(5, stream(1)) tries to consume an infinite data structure. This means that the program will either run out of memory or crash, and the output will be undefined.