首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >一个正确实现的递归延迟迭代器函数会不会出现堆栈溢出吗?

一个正确实现的递归延迟迭代器函数会不会出现堆栈溢出吗?
EN

Stack Overflow用户
提问于 2014-08-15 02:52:00
回答 1查看 1.5K关注 0票数 19

tl;dr;

在C#中,你能保证一个懒惰的迭代器函数只调用它自己,并且有一个有效的递归退出条件不会导致堆栈溢出吗?

详细问题:

我知道通常你不能保证C#编译器(或JIT)生成的尾部调用优化(TCO)指令,所以虽然你可能会得到TCO,但没有保证。

鉴于对总拥有成本的认识,我想知道惰性迭代器函数(使用yield return等)是否因为其作为协程的本质而被占用堆栈空间?我对协程的直觉是,因为它们的可重入性,每个尾部调用在默认情况下都是优化的,因为从父帧跳出并进入下一个函数的能力看起来很自然,而不是创建一个新的帧。

这是在C#中的行为,还是C#迭代器函数的递归调用从当前框架创建新框架,而不是弹出到父框架并使用新参数重新进入?

示例:

代码语言:javascript
复制
public static IEnumerable<IEnumerable<T>> GeneratePermutations<T>(this IEnumerable<T> choices, int numberToChoose)
{
    if (numberToChoose == 1)
    {
        foreach (var choice in choices)
            yield return new T[] { choice };
        yield break;
    }

    var subPermutations = choices.SelectMany(choice =>
        choices.Where(elem => !EqualityComparer<T>.Default.Equals(elem, choice))
            .GeneratePermutations(numberToChoose - 1)
            .Select(permutation => (new T[] { choice }).Concat(permutation)));
    foreach (var perm in subPermutations)
        yield return perm;
}

我的直觉是基于上面的例子subPermutations是一个简单的堆计算,似乎在调用迭代它时,它可以知道它是一个堆计算(它是函数sig的一部分,它是一个迭代器函数),因此立即跳出它的当前帧并将堆计算扩展到一个新帧--在尝试递归调用之前不会消耗额外的堆栈空间。

这种直觉可能是完全没有根据的。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25315542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档