在C#中优化尾调用

时间:2010-09-10 00:10:49

标签: c# tail-recursion tail-call-optimization

我有一个深度递归函数,即使在大输入的情况下理论上也应该可以很好地工作。问题是在撰写本文时我忘记了C#没有很好地进行尾调用优化,如果有的话,所以我得到StackOverflowException s用于任何复杂足够的输入。该方法的基本结构有两种大方法,每种方法都调用另一种方法。

public object Simplify(object param) {
    if (IsSimple(param))
        return param;
    else
        return Expand(param);
}

private object Expand(object param) {
    return Simplify(ProcessExpansion(param));
}

IsSimpleProcessExpansion都有相对固定的堆栈深度 - 唯一的问题是Simplify和Expand之间的递归。你会如何在这里减少堆栈深度?

我正在考虑返回会计算结果的代表,但这看起来有点矫枉过正 - 必须有一种更简单的方法。这是我对解决方案的想法(它不是很精致,因为我一直认为我必须在这里做一些可怕的错误):

public object Simplify(object param) {
    object result = () => SimplifyInternal(param);
    while (result is Func<object>)
        result = ((Func<object>)result)();
    return result;
}

private object SimplifyInternal(object param) {
    if (IsSimple(param))
        return param;
    else
        return Expand(param);
}

private object Expand(object param) {
    return () => SimplifyInternal(ProcessExpansion(param));
}

所以我的两个问题是:

  1. 这个解决方案有什么不可思议的错误?
  2. 你能想到一个更好的吗?

1 个答案:

答案 0 :(得分:8)

这不是

while(!IsSimple(param))
    param = ProcessExpansion(param);
return param;