导致“包含递归定义的序列表达式被错误编译"的原因是什么? [英] What reasoning lead to `Sequence expression containing recursive definition is compiled incorrectly`
问题描述
问题尽管尾部调用位置但仅在64位中,堆栈溢出导致发现在阅读答案之后,我对导致发现错误的原因感到好奇,因为我想做得更好提高我解决问题和了解总体拥有成本的技能.
After reading the answer I am curious as to the reasoning that lead to finding the bug as I would like to better improve my skills at resolving problems and understanding TCO.
推荐答案
我的推理是这样的:
在查看计算表达式时谈论尾部调用"可能会产生误导作用-一般来说,实际上没有这种事情(请参见例如
Talking about "tail calls" when looking at a computation expression can be misleading - in general there really isn't such a thing (see e.g. this other answer for one related discussion, though not related to sequence expressions).
因此,调用 gauss
本身不会使堆栈溢出,只有对其进行迭代的代码才可能使堆栈溢出.但是一旦我看到调用代码就像 Seq.nth
之类的东西,那意味着几乎肯定有一个编译器错误,因为"tail yield!
ing"模式"中的序列表达式应该进行了优化(不确定这是否是规范的一部分,但我认为它是众所周知的).因此,这只是查看初始复制的哪些部分是必要的情况.
So calling gauss
will not itself ever overflow the stack, only the code iterating through it could make it overflow. But once I saw that the calling code was just something like Seq.nth
, that meant that there was almost certainly a compiler bug, because the pattern of "tail yield!
ing" in a sequence expression is supposed to get optimized (not sure if this is part of the spec, but I think it's fairly well known). So then it was just a case of seeing what parts of the initial repro were necessary.
使用非递归定义替换原始代码中的循环会使repro停止失败,就像删除模式匹配一样.我发现对IL并没有帮助(在序列表达式的编译中涉及到很多由编译器生成的机制),我只是尝试在源代码级别上最小化repro并凭经验测试行为.
Replacing loop in the original code with a non-recursive definition made the repro stop failing, as did removing the pattern match. I didn't find looking at the IL helpful (there's so much compiler-generated machinery involved in the compilation of sequence expressions), I just tried minimizing the repro at the source level and empirically testing the behavior.
这篇关于导致“包含递归定义的序列表达式被错误编译"的原因是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!