我有一些类似代码的示例,它不完全是递归委托,但它很接近。“Y-Combinator”接近了——坦率地说,我不知道它在实践中是如何工作的,但它用于定义递归函数。
这是您需要定义的时髦代码:
public delegate T S<T>(S<T> s);
public static T U<T>(S<T> s)
{
return s(s);
}
public static Func<A, Z> Y<A, Z>(Func<Func<A, Z>, Func<A, Z>> f)
{
return U<Func<A, Z>>(r => a => f(U(r))(a));
}
现在您可以在一行中定义递归函数。
阶乘:
var fact = Y<int, int>(_ => x => x == 0 ? 1 : x * _(x - 1));
var fact5 = fact(5); // == 120
var fact6 = fact(6); // == 720
var fact7 = fact(7); // == 5040
斐波那契:
var fibo = Y<int, int>(_ => x => x <= 1 ? 1 : _(x - 1) + _(x - 2));
var fibo5 = fibo(5); // == 8
var fibo6 = fibo(6); // == 13
var fibo7 = fibo(7); // == 21
我最喜欢的代码行是 call s(s)
。说真的,如果有人能在头脑中理顺这一点,那他们就是天才!更别说整体了U<Func<A, Z>>(r => a => f(U(r))(a))
。