函数式c#和尾部递归
本文关键字:尾部 递归 函数 | 更新日期: 2023-09-27 18:02:20
我有以下代码:
public static IEnumerable<T> cons<T>(T y, IEnumerable<T> xs)
{
yield return y;
foreach (var x in xs) yield return x;
}
public static bool empty<T>(IEnumerable<T> xs)
{
return !xs.GetEnumerator().MoveNext();
}
public static T head<T>(IEnumerable<T> xs)
{
Debug.Assert(!empty(xs), "Prelude.head: empty list");
var e = xs.GetEnumerator(); e.MoveNext();
return e.Current;
}
// repeat x is an infinite list, with x the value of every element
public static IEnumerable<T> repeat<T>(T x)
{
return cons(x, repeat(x));
}
为什么head(repeat(2))
不工作,但如果我用:
repeat
的实现// repeat x is an infinite list, with x the value of every element
public static IEnumerable<T> repeat<T>(T x)
{
for(;;) yield return x;
}
工作吗?
您的第一个实现不是尾部递归的。最后要执行的是cons()
调用,但是为了执行它,它必须计算repeat(2)
。要做到这一点,它必须(再次)计算repeat(2)
。依此类推,直到堆栈溢出。
第二个实现创建了一个枚举器,每次被要求输入下一个元素时,它都会无限期地返回x。没有重入,所以没有堆栈溢出
从表面上看,您的第一个示例从未终止,因此它只是破坏了堆栈。第二个示例是作为状态机实现的,它可以避免堆栈溢出。