2012-11-30 14 views
5

これはスタックオーバーフローの問題について人々が尋ねている問題の逆ですが、関数を作成して次のように呼び出すとエラーは起こりません。アプリケーションは単にコアを分割します私のCPUの私はそれを強制終了するまで:F#で無限再帰がスタックオーバーフロー例外に当たっていないのはなぜですか?

let rec recursionTest (x: uint64) = 
    recursionTest (x + 1UL) 

recursionTest 0UL 

この方法で私は時々私のコードにブレークポイントを置くことができます:それは実際にこのような何かをして

もちろん
let rec recursionTest x = 
    recursionTest x 

recursionTest 1 

私はこれを変更することができますxの値がかなり速く上がっているのを見ても、それでも文句はありません。 F#は無限回帰に気を付けませんか?

答えて

8

あなたrecursionTest関数は、関数の最後のアクションとして「尾部の位置」、すなわちで発生するすべての再帰呼び出しを意味テール再帰的、です。つまり、F#コンパイラは再帰呼び出しに新しいスタックフレームを割り当てる必要がないため、スタックオーバーフローは発生しません。

テール再帰は、tail callの特殊なケースです。テールコールは、他の機能ではなく、それ自体になります。一般に

+0

ありがとう、それはVSが呼び出しスタックウィンドウでより多くの呼び出しを表示していなかった理由についての記載されていない質問についても説明しました。 – Amazingant

+1

実際、この場合、F#コンパイラは実際にコードをループに変換します。コンパイルされたコードには実際には再帰はありません。 –

4

、F#が.NET優等ことtailcall命令を発するいくつかの特定の単純なケースでは

http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.tailcall(v=vs.95).aspx

、あなたのような、F#は、ループを使用して、同等のプログラムに再帰を使用するプログラムを書き換えます。

+0

アプリをIL Disassemblerまたはリフレクターに投げ込むのにもう少し時間がかかったら、おそらくこれを見ていたでしょう。追加の背景情報をありがとう。 – Amazingant

関連する問題