仍然出现堆栈溢出异常

仍然出现堆栈溢出异常

本文介绍了F#使用累加器,仍然出现堆栈溢出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下功能中,我试图通过使用累加器来设置尾递归。但是,我遇到了堆栈溢出异常,这使我相信我设置函数的方式没有正确启用尾部递归。

In the following function, I've attempted to set up tail recursion via the usage of an accumulator. However, I'm getting stack overflow exceptions which leads me to believe that the way I'm setting up my function is't enabling tail recursion correctly.

//F# attempting to make a tail recursive call via accumulator
let rec calc acc startNum =
    match startNum with
    | d when d = 1      -> List.rev (d::acc)
    | e when e%2 = 0    -> calc (e::acc) (e/2)
    | _                 -> calc (startNum::acc) (startNum * 3 + 1)

根据我的理解,使用 acc 将允许编译器看到不需要为每个递归调用保留所有堆栈帧,因为它可以将每次传递的结果填充到acc中并返回从每一帧。对于如何正确使用累加器值,显然我不了解,因此编译器会进行尾部调用。

It is my understanding that using the acc would allow the compiler to see that there is no need to keep all the stack frames around for every recursive call, since it can stuff the result of each pass in acc and return from each frame. There is obviously something I don't understand about how to use the accumulator value correctly so the compiler does tail calls.

推荐答案

斯蒂芬·斯文森(Stephen Swensen)正确地指出,如果您进行调试,VS必须禁用尾部调用(否则它将没有堆栈框架来跟随调用堆栈)。我知道 VS是这样做的,但是只是忘记了。

Stephen Swensen was correct in noting as a comment to the question that if you debug, VS has to disable the tail calls (else it wouldn't have the stack frames to follow the call stack). I knew that VS did this but just plain forgot.

在被这一点咬住之后,我想知道运行时或编译器是否可能抛出更好的异常,因为编译器知道您正在调试并且您编写了递归函数,在我看来,它可能会给您一个提示,例如

After getting bit by this one, I wonder if it possible for the runtime or compiler to throw a better exception since the compiler knows both that you are debugging and you wrote a recursive function, it seems to me that it might be possible for it to give you a hint such as

'Stack Overflow Exception: a recursive function does not
tail call by default when in debug mode'

这篇关于F#使用累加器,仍然出现堆栈溢出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-19 21:38