Recursive Lambda Expressions in C#

The first two samples, loop & loop2, show you a recursive Lambda Expression. The first version has some console outputs for debugging. I’ve also added a sample that gives you the 10th Fibonacci number.

The other samples are just showing you some syntactic sugar that can be used when working with Lambda Expressions.

using System;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Func<int, string> consoleResult = x => string.Format("Result: {0}" + Environment.NewLine, x);

// loop version 1 (debug)
Func<int, int> loop = null;
loop = x => { Console.WriteLine(x); return x == 0 ? 1 : x * loop(x - 1); };
Console.WriteLine(consoleResult(loop(5)));

// loop version 2
Func<int, int> loop2 = null;
loop2 = x => x == 0 ? 1 : x * loop(x - 1);
Console.WriteLine(consoleResult(loop2(5)));


// Fibonnaci
Func<int, int> fib = null;
fib = x => x < 2 ? x : fib(x - 1) + fib(x - 2);
Console.WriteLine(consoleResult(fib(10)));

//-----------------------//
// Some other examples
//-----------------------//

// version 1
Func<int, int> calc = null;
calc = (x) => { Console.WriteLine(x); return x >= 1024 ? x : calc(x * 2); };
Console.WriteLine(consoleResult(calc(2)));

// version  2
Func<int, int> calc2 = null;
calc2 = x => x >= 1024 ? x : calc2(x * 2);
Console.WriteLine(consoleResult(calc2(2)));

// version 3
Func<int, int> calc3 = null;
calc3 = x => x >= 1024 ? x : calc3(x * 2);
Console.WriteLine(consoleResult(calc3(2)));

// version 4
Func<int, int> calc4 = null;
calc4 = x => { return x >= 1024 ? x : calc4(x * 2); };
Console.WriteLine(consoleResult(calc4(2)));

// version 5
Func<int, int> calc5 = null;
calc5 = (x) => x >= 1024 ? x : calc5(x * 2);
Console.WriteLine(consoleResult(calc5(2)));

// version 6
Func<int, int> calc6 = null;
calc6 = (x) => { return x >= 1024 ? x : calc6(x * 2); };
Console.WriteLine(consoleResult(calc6(2)));

// Don't close the console directly
Console.ReadLine();
}
}
}

You will see a compiler error Use of unassigned local variable ‘fib’  when you try something like this:

Func<int, int> fib = x => x < 2 ? x : fib(x - 1) + fib(x - 2);

The compiler cannot use fib because it is not yet assigned.
(Depends on which side the C# Compiler evaluates first).

Have fun exploring Lambda Expressions, recursion and Func<T, TResult> 😉

Advertisements

C# Expression Trees

Just a quick example that you can try yourself. It can be hard to write and debug Expression Trees but they are very powerful.

using System;
using System.Linq.Expressions;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Func<int, int> f = (x) => x + 1; // Same as: x++
var result = f(1);
Console.WriteLine("My result: " + result);

// ------

var result2 = f.Invoke(1);
Console.WriteLine("My result (via Invoke): " + result2);

// ------

ParameterExpression param0 = Expression.Parameter(typeof(int)); // first parameter
ParameterExpression param1 = Expression.Parameter(typeof(int)); // second parameter
ConstantExpression const0 = Expression.Constant(1);             // a constant

BinaryExpression expr = Expression.Add(Expression.Subtract(param1, const0), param0); // Same as: param1 - constant + param0
Expression<Func<int, int, int>> lambdaExpr = Expression.Lambda<Func<int, int, int>>(expr, param0, param1); // creates the lambda delegate

Func<int, int, int> compiledExpr = lambdaExpr.Compile(); // compiles the expression tree
var result3 = compiledExpr(1, 1); // executes the epxression tree with param0 and param1

Console.WriteLine("My result via Expression: " + result3);

// Don't close the console directly
Console.ReadLine();
}
}
}

See also the ExpandoObject in C#.

Enjoy 😉