Matt Follett

Week 3: Lazy Evaluation

One of the popular concepts in functional programming is the concept of lazy evaluation.  For code to be lazily evaluated it means that instead of being evaluated at the point when the system reaches it it is instead evaluated at the point that the results are needed.  The concept of lazy evaluation exists in lots of languages; Perl 6 uses them for lists, as does Python, and languages like Haskell, Clojure, and others use them quite frequently.  In fact, at the latest Clojure Cljub meeting one developer was complaining that Clojure was so lazy it was hard for him to tell when it was doing nothing at all.

The benefits of having the ability to lazily evaluate code show up in many cases.  Lazy evaluation can allow developers to represent “infinite streams” because the only portion of the stream that is computed is the portion that the program needs to perform its task.  Without lazy evaluation the program would try and compute all possible values and never complete.  Additionally, things like Moose use this concept to allow a developer to lazily evaluate attribute construction.  This is hugely beneficial because it means that attributes that take a long time to construct will only be constructed when they are needed, instead of on the main object’s construction.  DBIx::Class also uses this, the query to the database doesn’t happen when ‘search’ is called on the DBIx::Class object.  Instead, it is called when the first piece of data is retrieved.  This allows DBIx::Class to wait and collect as much information about what the query really needs to be before it executes it, saving precious database time by not making wasteful queries.  A final example would be Object::Trampoline, which can delay the construction of an object and the loading of modules.

So, how do we lazily evaluate code in Perl 5?  We simply wrap it in a subroutine.  Let’s say, for example, we wanted to make a stream that generated the set of all natural numbers (N), which is simply all the integers ≥ 0.  We would simply write something like this:

Now, each time we want a new natural number we can call the anonymous subroutine and a new one will be generated.  We could then use this in a while loop:

Another benefit of this approach is that we can now provide streams of numbers logically separated from the looping method (which is a common benefit of iterators).  So, for example, we could use these two streams with the same while loop:

Obviously, we could do considerably more interesting things than this.  MJD’s Higher Order Perl talks about creating lazy linked lists in chapter 6.2.