## 使用Lambda表达式编写递归函数

2009-08-31 01:40  Jeffrey Zhao  阅读(22796)  评论(62编辑  收藏  举报

# 伪递归

Func<int, int> fac = x => x <= 1 ? 1 : x * fac(x - 1);

Func<int, int> fac = null;
fac = x => x <= 1 ? 1 : x * fac(x - 1);

x => x <= 1 ? 1 : x * fac(x - 1);

Func<int, int> fac = null;
fac = x => x <= 1 ? 1 : x * fac(x - 1);
Console.WriteLine(fac(5)); // 120;

Func<int, int> facAlias = fac;
fac = x => x;
Console.WriteLine(facAlias(5)); // 20

facAlias(5)     <— facAlias是x => x <= 1 ? 1 : x * fac(x – 1)
= 5 <= 1 ? 1 : 5 * fac(5 - 1)
= 5 * fac(4)    <— 注意此时fac是x => x
= 5 * 4
= 20

# 把自己传给自己吧

x => x <= 1 ? 1 : x * fac(x - 1);

(f, x) => x <= 1 ? 1 : x * f(f, x - 1);

var selfFac = (f, x) => x <= 1 ? 1 : x * f(f, x - 1);

Console.WriteLine(selfFac(selfFac, 5)); // 120;

delegate int SelfFactorial(SelfFactorial selfFac, int x);

delegate TResult SelfApplicable<T, TResult>(SelfApplicable<T, TResult> self, T arg);

SelfApplicable<int, int> selfFib = (f, x) => x <= 1 ? 1 : f(f, x - 1) + f(f, x - 2);
Console.WriteLine(selfFib(selfFib, 5)); // 8

SelfApplicable<int, int> selfFac = (f, x) => x <= 1 ? 1 : x * f(f, x - 1);
Func<int, int> fac = x => selfFac(selfFac, x);

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

static Func<T, TResult> Make<T, TResult>(SelfApplicable<T, TResult> self)
{
return x => self(self, x);
}

var fac = Make<int, int>((f, x) => x <= 1 ? 1 : x * f(f, x - 1));
var fib = Make<int, int>((f, x) => x <= 1 ? 1 : f(f, x - 1) + f(f, x - 2));

// 委托类型
delegate TResult SelfApplicable<T1, T2, TResult>(SelfApplicable<T1, T2, TResult> self, T1 arg1, T2 arg2);

// 辅助方法
static Func<T1, T2, TResult> Make<T1, T2, TResult>(SelfApplicable<T1, T2, TResult> self)
{
return (x, y) => self(self, x, y);
}

var gcd = Make<int, int, int>((f, x, y) => y == 0 ? x : f(f, y, x % y));
Console.WriteLine(gcd(20, 36)); // 4

# 不动点组合子

static Func<T, TResult> Fix<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> f)
{
return x => f(Fix(f))(x);
}

static Func<T1, T2, TResult> Fix<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> f)
{
return (x, y) => f(Fix(f))(x, y);
}

Fix求出的是函数f的不动点，它就是我们所需要的递归函数：

var fac = Fix<int, int>(f => x => x <= 1 ? 1 : x * f(x - 1));
var fib = Fix<int, int>(f => x => x <= 1 ? 1 : f(x - 1) + f(x - 2));
var gcd = Fix<int, int, int>(f => (x, y) => y == 0 ? x : f(y, x % y));

var qsort = Fix<IEnumerable<int>, IEnumerable<int>>(f => l => l.Any() ? f(l.Skip(1).Where(e => e < l.First())).Concat(Enumerable.Repeat(l.First(), 1)).Concat(f(l.Skip(1).Where(e => e >= l.First()))) : Enumerable.Empty<int>());