Search code examples
c#recursionlambdaanonymous-recursion

Howto: "letrec" in C# (lambda expression call within its definition)


Consider the factorial function defined within a method body as a lambda expression and assigned to a variable:

Func<int, int> factfail = n =>
{
    if (n == 0)
        return 1;
    else
        return n * factfail(n-1);
};

This fails, since factfail isn't bound by the the local variable yet.

Is there a way to add a sort of fixpoint - by abstracting over the function itself?!

Func<Func<int, int>, int, int> fact_ = (fact, n) => 
{  
    if (n == 0) 
        return 1;
    else 
        return n * fact(n-1); 
};

fact_(??);

long story: I need to write a recursive function that has the side effect of changing some outer state. Therefore i am trying to write that method as a lambda expression that captures that outer state.

I am still experimenting with different styles how to write that and - besides of that one dictionary that needs to be the same for all recursive calls - i want to be as purely functional and lazy as possible.

So i was playing with LINQ, since it helps me reducing mutual data. It also helps with understanding which parts of the code can be expressed in a functional style.

To be brief in the LINQ statement it is helpful to be able to define some helper functions in front of and i did that by binding lambda expressions to variables.

And with lamda expression i also can capture my dictionary without the need to pass its reference to the method explicitely, which is quite nice.

not sure if i am on the right track though...


Solution

  • You can find more information about recursive lambda expressions in this blog post by Mads Torgersen. He shows how to define the usual fixed point combinator. He uses factorial function as an example, so you can find your exact sample there :-).

    However, in practice, you can just define a local Func<..> variable and then mutate it. If you want to give a name to the delegate, then it works just fine (it is a bit dirty, but simple):

    Func<int, int> fact = null;
    fact = (n) => (n == 0) ? 1 : n * fact(n-1);
    

    This works, because the closure captures reference to the fact variable, so when you actually call it (during the recursive call), the value is not null anymore, but references the delegate.