Lazy evaluation

From Nemerle Homepage

Contents

Introduction

Sometimes we know that a given expression will be evaluated only on some (maybe rare) computation paths. When it is just a simple operation we do not care about it - the more important fact for us is that declaring a variable initialized with this expression is making our code cleaner. But when computing a given expression is expensive in performance, we would like it to be evaluated only when needed.

This is one of the applications for lazy evaluation.

Basic example

using System;
using Nemerle;
 
class M
{
  static foo ([Lazy] x : int, y : bool) : void {
    if (y) {
      Console.WriteLine (x);
      Console.WriteLine (x);
    }
    else
      Console.WriteLine ("nothing");
  }
 
  static SideEffect : int {
    get {
      Console.WriteLine ("somebody is fetching me");
      1
    }
  }
  
  public static Main() : void
  {
    def laz = lazy (SideEffect + 1);
    foo (laz, false);
    foo (laz, true);
  }
}

will print

nothing
somebody is fetching me
2
2

Infinite lists

Lazy evaluation allows us to implement infinite lists easily. The node of our list presented below has two fields - current value in Val and reference to the next element in Next. But the instance contained in Next is a lazy value, so it will be evaluated only when requested.

class InfList {
  public Val : int;
  public Next : LazyValue [InfList];
 
  public this (v : int) {
    Val = v;
    Next = lazy (InfList (v + 1)); 
  }
}

Note that we can use InfList just like it was a standard list. We can iterate over it in a loop and everytime when Next is accessed, the new node is created and memoized.

mutable inflist = InfList (0);
repeat (10) {
  Nemerle.IO.printf ("%d ", inflist.Val);
  inflist = inflist.Next;
}

Source

remember
You are very welcome to contribute to the documentation here!