Home > Net >  How does the compiler make delegate achieve lazy computation?
How does the compiler make delegate achieve lazy computation?

Time:01-12

I am learning lazy computation, given by the code below

public static Func<R> Map<T, R>(this Func<T> f, Func<T, R> g)
{
   return () => g(f());
}

because f could be a computing expensive function to generate T, that's why it is wrapped as Func<T>, but Map returns () => g(f()), where f() is more like a closure which has to be ready first, so it looks to me that f() will still be evaluated in () => g(f()), I know my understanding is wrong, but I couldn't figure what's wrong, so how does compiler kicks in and makes the code still lazy computation (i.e f() will not be called in () => g(f())?

CodePudding user response:

() => g(f()) denotes an anonymous function, nothing more.

Nothing within that function is evaluated at the point of declaration.

f() is only invoked when that anonymous function is invoked, and is invoked every time the anonymous function is invoked.

CodePudding user response:

() => g(f()) is an lambda expression which creates an anonymous function (which is actually a syntactic sugar translated by compiler - see @sharplab).

so it looks to me that f() will still be evaluated in () => g(f())

Yes, when the anonymous function represented by () => g(f()) will be called/evaluated, i.e. (pseudocde):

Func<_> x = () => g(f()); // nothing is evaluated here
x(); // f and g are evaluted here

So laziness is achieved by the fact that computation will be performed not when Map is called but when it's result is invoked, which is easy to check with side-effect. The following:

Func<int> returnsInt = () => 1;
Func<string> mapped = returnsInt.Map(i =>
{
    Console.WriteLine("Inside mapping func");
    return $"Int is: {i}";
});
// nothing printed yet
Console.WriteLine("Before the eval");
Console.WriteLine(mapped());

Gives next output:

Before the eval
Inside mapping func
Int is: 1

  • Related