2012-04-04 4 views
3

Tclでスタックを簡単に展開する方法はありますか? 私は文字通り特定のスタックフレームに戻る必要があるこの奇妙な問題を抱えています。 infoコマンドを使用してすべてのフレーム情報を取得できますが、実際に特定のフレームに到達するには、各プロシージャにローカル変数をいくつか設定し、それに応じてチェックする必要があります。私は簡単な方法があるかどうか疑問に思っていました。別のTclスタックフレームに戻る

+0

デバッグまたは...? –

+0

実行中。私は、ある手続きから別の手続きに移行する必要があります。 – ilya1725

+0

ドナル・フェローの答えは完璧だと思うが、「スタックをアンロールする」という言葉は、ほとんどのプログラマーの心にある例外処理/デバッグに深く関わっている用語なので、主語の言い直しが必要である。どのようにして賢明に言い換えるのか? – kostix

答えて

4

ローカル以外のリターンを行うためにコードを取得する必要がある場合(すなわち、いくつかのレベルをバックスキップ)あなたは、以降returnから-levelオプションで8.5からこれを行うことができます。次の例を参照してください。

proc foo-a {} { 
    puts a-in 
    foo-b 
    puts a-out 
} 
proc foo-b {} { 
    puts b-in 
    foo-c 
    puts b-out 
} 
proc foo-c {} { 
    puts c-in 
    foo-d 
    puts c-out 
} 
proc foo-d {} { 
    puts d-in 
    bar 
    puts d-out 
} 
proc bar {} { 
    puts bar-in 
    return -level 3 
    puts bar-out 
} 
foo-a 

これは特別な種類の例外をスローすることで機能します。詳細はかなり隠されています。また、8.6またはスクリプト化された実装がある場合は、trythrowを使用することもできます(8.6のコードの説明で使用されたTclコードのTcler's Wikiを参照)。それがここにマジック値(42の場合は、古いTclのバージョンで

は、最も簡単なメカニズムはreturn -code 42を使用すると、最大スタックcatchに代わってカスタム例外をいくつかのコードを入れて、決定することであり、それは結果になるだろうcatch)、適切に応答します。これは非常に効果的ですが、面倒です。 8.5以降では、使いやすいツールが提供されます。

3

簡単な答えは、おそらくあなたのデザインを考え直す方がよいだろうということです。

長い答えはこれを行うための唯一の実際の方法(私が考えることができる)は、エラーを投げ、それを停止する必要があるレベルでバックアップをキャッチすることです。もちろん、コールスタックのすべての方法で変数をチェックするのに難しい方法ではありません。しかし、制御フローにエラーを使用すると、悪い形になります。

1

あなたが最先端になりたいなら、コルーチン(8.6で利用可能)があなたのニーズを満たすかもしれません。

そうでなければ、そこにいるとき(グローバル変数を[info level]に設定する)に必要なルーチンのレベルを書き留めてから、深いproc [ uplevel]を絶対スタックフレームに追加します。ような何か

proc need-to-be-here {} { 
    set ::myframe [info level] 
    deeper-calls 
} 

proc deepest-call {} { 
    uplevel #$::myframe {what I need to do} 
} 

(未テスト)

+0

+1は、「アップレベル」を悪用するためのものです。私が維持しなければならないコードのようなものを使用しないでください! :-) –

関連する問題