2010-12-06 11 views
1

私はthis blogを読んでいますし、例外が発生したら、その後ルビーは全体のスタックトレースをクリアし、例外のスタックであることを交換しなければならない、動作するように上記のコードのためのように思えるのコード例外は何のスタックトレースをクリアしますか?

RunAgain = Class.new(Exception) 
def fib(i, n = 1, result = 0) 
    if i == -1 
    result 
    else 
    raise RunAgain 
    end 
rescue RunAgain 
    i, n, result = i - 1, n + result, n 
    retry 
end 

を次のように出会いました。

私の理解は正しいですか?

答えて

2

このコードの動作方法は、実際にはスタックトレースとは関係ありません。スタック全体に2つのエントリ、fibfibの呼び出し元があります。例外の発生はあなたの疑問に赤い鳴き声のようなものです。この例では、retryの動作のデモンストレーション以外の有用な目的はありません。

ルビーのretryは、next,breakredoなどの他の制御キーワードと似ています。 redoキーワードは、現在のループまたはブロックを先頭から再試行することを意味します。 retryキーワードはレスキュー内で動作し、例外をスローした現在のブロックを再試行します。

ので、いくつかの初期値はin、およびresultに設定され、ここでされて何が起こるか、ベースケースは、(i == -1)がチェックされ、満たされていない場合、我々は値を更新し、上から再試行してください。これらの値はメソッドパラメータでありローカル変数ではないため、再初期化されないことに注意してください。フィボナッチので

慎重には、再帰的なアルゴリズムのためにこれを間違えないよう、非常に一般的な例(および1つの非常に乏しい)再帰のです。 RunAgain raiseおよびrescue関数は、関数の呼び出しや呼び出しスタックの修正を行うことなく、ループのように機能します。

あなたのコード例ではiがちょうどカウンターとの何物でもあり、どちらの場合に注意

def fib(i) 
    n, result = 1, 0 
    (i+1).times { n, result = n + result, n } 
    result 
end 

に相当します。私たちはコードi+1回を実行します。値を交換するための一時変数の一般的な必要性は、ルビの複数の代入構造で置き換えられることにも注意してください。

+0

私は大きな値のためにフィボナッチを求めていた場合は、その後上げ千万の例外が存在します。すべての例外情報がスタックに保持されていると、スタックトレースエラーが最終的にスローされます。したがって、私の質問は、スタックトレース情報がスタックから削除され、次の例外が発生したときです。 –

+1

@Nadalは、私の応答の第二の文を参照してください。 「スタック全体の時間の2つのエントリがあります。」あなたの例では、ゼロ再帰を持っており、発生した例外は、スタック上の影響はありません。 –