I recently picked up and continued reading "Coders At Work" by
Peter Seibel. It's a great read, very inspiring and insightful,
but I got kind of tired of the dialogue-heavy format when I was
plowing through it the last time.
Anyway, I got to the chapter of Simon Peyton Jones, where he had a
lot to say about the merits of lazy evaluation.
I've always thought lazy evaluation was a mechanism for making code
act more like math. And since it's notoriously difficult to reason
about runtime complexity of a lazy program, I sort of relegated
lazy evaluation into the "cool, cute and neat"-compartment of my
toolbox. I didn't realize that lazy evaluation is also a very
powerful tool for separating producer and consumer of an algorithm.
For instance, if you're making a chess program, you can have one
part generating all possible moves and keep it separate from a
consumer that drives the computation by walking a decision tree.
This is typically something that you don't really rely on in an
eagerly evaluated language, but become second nature in a lazy
language. (Generators in languages such as Python allow this kind
of style, although it isn't the main selling point of the
language.)
I thought it was cool, and will definitely re-evaluate my stance. :)