简体   繁体   中英

C# anonymous function recursion

Please correct me if I am wrong but I could not find anything straight forward like this online. Assuming you have the following:

        static Func<int,int> GetInt(int n)
        {
            return (int y) =>
            {
                if (y < 2)
                    return (y);
                return 
                    GetInt(n - 1)(y) - GetInt(n - 2)(y);
            };
        }

Trying to get the result by calling this anonymous function is returning something like System.Func`2[System.Int32,System.Int32]. How can you achieve recursion using anonymous functions. How could I cast the return value which is the actual function in order to get the result?

it seems like you're calling the function as follows:

var result = GetInt(valueOfN);

Note that the above GetInt method returns a function itself. Thus to get the result returned by the inner function you'd need to do:

var result = GetInt(valueOfN)(valueOfY);

It looks like you've munged up the function.

The variable n isn't being used to create the Func<int, int> in any way and the variable y is not being modified. The Func<int, int> will therefore just cause a stack overflow.

If I assume that y and n were meant to be the same variable then your method really boils down to this:

static Func<int,int> GetInt()
{
    Func<int, int> f = y =>
    {
        if (y < 2)
            return y;
        return 
            f(y - 1) - f(y - 2);
    };
    return f;
}

But this gives me an error:

Use of unassigned local variable 'f'

And that just leads us back to your question:

How can you achieve recursion using anonymous functions?

It's easy. Just assign null to the function first, then you can use recursion.

That gives me:

static Func<int,int> GetInt()
{
    Func<int, int> f = null;
    f = y =>
    {
        if (y < 2)
            return y;
        return 
            f(y - 1) - f(y - 2);
    };
    return f;
}

And this works perfectly fine.

As mentioned in other answers the code in the question

  • does not call resulting function and instead prints ToString() of resulting type which is indeed System.Func'2[System.Int32,System.Int32] ( answer by Ousmane D.
  • the code is infinite recursion as it never checks value of n ( answer by Optional Option )

What you are likely after is Y-combinator (or fixed-point combinator) which can be said converts non-recursive function into recursive one. That covered in many articles and SO questions like Do we need fixed point combinators in C#? , Have I implemented Y-combinator using C# dynamic, and if I haven't, what is it? .

You probably can start with less complicated variant which shows up on intermediate step of coming up with the complete code of y-combinator:

  • Recursive function can be represented as function that takes parameter and function to call recursively. Note that GetInt does not call itself recursively, it calls "some" function recursively, so this is not strictly "safe" approach - for complete implementation see links above.

    static int GetInt(Func f, int n) { return n < 2? 1: f(n - 1) - f(n - 2); }

  • To call that function with itself we need to convert that function (which has type Func<Func<int,int>, int, int> ) into Func<int, int> and pass it as first argument. So we can create helper method that does it. In method below r is "function that recursive function should call to do recursion". Note that we have to initialize it first as we use its value to define the resulting function:

     Func<int, int> Rec(Func<Func<int, int>, int, int> f) { Func<int, int> r = null; r = n => f(r, n); return r; }
  • Now we can make anonymous recursive function:

     Func<int,int> recursiveGetInt = Rec(GetInt); Console.WriteLine(recursiveGetInt (5)); Func<int,int> anonymousFactorial = Rec((f, n)=> n == 1? 1: n * f(n-1)); Console.WriteLine(anonymousFactorial (5)); Console.WriteLine("Anonymous Fibonacci of 5: {0}", ((f, n)=> n == 1? 1: f(n-1) + f(n-2)) (5));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM