Lazy Evaluation in C#

I started looking at Haskell and one thing that was interesting was the lazy evaluation. This allows you to write very generic functions and then chain other functions on top of it to do something on that data. This makes the programming feel more verbose and readable. Lets say if you want to get the first 10 fibonnaci number then following function

take 10 fibonnaci

is much more verbose and readable then

get_fibonnaci 10

How its done in haskell is that

fibonnaci = [fib x | x <- [1..]]

Here we are creating an infinite list and then calling a function fib on the numbers from the list. So if you call this function alone it will try to create an infinte list of all fibonnaci numbers and your shell will go into infinite loop. But if you add take 10 before it then it will only take 10 elements from your fibonnaci series as it will not evaluate the fibonnaci completely when its called with take 10 instead it will only call it until it meets the criteria to get only 10 items out of it. Hence it is called lazy evaluation or deffered evaluation as its lazy evaluating the function to only get what is needed.

We can actually do the same thing in C#. The yield return creates a state machines and allows you to do the same thing but the performance in C# is not as good as in Haskell.

public static class Fibonnaci  
{
    public static IEnumerable<long> Series()
    {
        long prevN1 = 1;
        long prevN2 = 1;

        yield return prevN1;

        yield return prevN2;

        while(true)
        {
            long temp = prevN1 + prevN2;
            prevN1 = prevN2;
            prevN2 = temp;
            yield return temp;
        }
    }
}

You might wonder that i got a bug as its a never ending loop, but you are right and wrong. If we call this function in isolation it will certainly become an infinite loop, but when I call this function chained up by other functions in LINQ library then this will work. They way to use it is

var firstTenFib = Fibonnaci.Series().Take(10)

It will do the same thing as Haskell i.e. the Take function will call the Fibonnaci function only 10 times and each call to the Fibonnaci function will return the next fibonnaci number in the series. This makes it more verbose and readable and reusable code.
So if you want to get first ten even fibonnaci numbers then you do something like this

var tenEvenFib = Fibonnaci.Series().Where(i => i%2==0).Take(10);

Isn't it cool :)

But be aware the performance of this wont be good in C# as compared to Haskell.

comments powered by Disqus

Subscribe to the new blog posts

* indicates required