1

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?

Darwins
  • 23
  • 3
  • 2
    ...but why with an anonymous function? Name that puppy and make it more understandable? – Idle_Mind Jun 04 '20 at 22:25
  • What exactly is the point of this function? The first call will return the anonymous function and subsequent calls would call creation of more anonymous functions. I do not think the idea was to make the function that inneficient – Optional Option Jun 04 '20 at 23:14
  • @OptionalOption that's a first step to writing proper anonymous recursive functions... Mostly educational exercise but useful to gain deeper understanding of language - https://weblogs.asp.net/dixin/lambda-calculus-via-csharp-7-fixed-point-combinator-and-recursion, or search for "C# y combinator" (not to be confused with site of the same name). – Alexei Levenkov Jun 04 '20 at 23:50
  • Note that it is very confusing what you expect this code to do (and what shown in the post will stack overflow as @OptionalOption pointed out)... Usually people start with n! or Fibonacci numbers when they experiment with recursion - sample in the question is very confusing in what value it tries to compute. – Alexei Levenkov Jun 05 '20 at 00:06
  • The variable `n` isn't even being used in this function. It's been munged. – Enigmativity Jun 05 '20 at 00:15

3 Answers3

1

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);
Ousmane D.
  • 50,173
  • 8
  • 66
  • 103
  • This is guaranteed stack overflow. – Optional Option Jun 04 '20 at 23:43
  • 1
    @OptionalOption while that might be the case. it's a completely different matter to the question asked. question asked was "how to invoke the inner function" not "what problems could arise and how to fix them". that's for the OP to look into and fix. I didn't pay too much attention to what the code actually did at the time of this post otherwise I would have noticed and suggested something but as said that's completely irrelevant to the question and would have just been a bonus for me to mention. – Ousmane D. Jun 05 '20 at 09:06
  • This is not a anonymous function calling itself recursively. It is an anonymous function that recursively creates other anonymous functions. – Optional Option Jun 05 '20 at 15:13
1

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.

Enigmativity
  • 97,521
  • 11
  • 78
  • 153
0

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));
    
Alexei Levenkov
  • 94,391
  • 12
  • 114
  • 159