Tcl でスタックをアンロールする簡単な方法はありますか? 文字通り、特定のスタックフレームに戻らなければならないという奇妙な問題があります。コマンドを使用してすべてのフレーム情報を取得できますinfo
が、実際に特定のフレームに到達するには、各プロシージャでいくつかのローカル変数を設定し、それに応じてチェックする必要があります。もっと簡単な方法はないかと考えていました。
3 に答える
非ローカル リターン (つまり、いくつかのレベルをスキップして戻る) を行うコードを取得する必要がある場合は、-level
オプション to を使用して 8.5 以降でこれを行うことができますreturn
。次の例を参照してください。
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 またはそれらのスクリプト化された実装がある場合はtry
、 andを使用することもできます ( 8.6 のコードの説明中に使用された Tcl コードについては、 Tcler の Wikiを参照してください)。throw
古い Tcl バージョンでは、最も簡単なメカニズムは、return -code 42
いくつかのコードを使用してカスタム例外のアップスタックに配置しcatch
、それがマジック値 (ここでは 42; の結果) であるかどうかを判断し、catch
適切に応答することです。これは非常に効果的ですが、面倒でもあります。そのため、8.5 以降ではより使いやすいツールが提供されます。
簡単に言えば、デザインを再考したほうがよいでしょう。
より長い答えは、これを行う唯一の実際の方法 (私が考えることができる) は、エラーをスローし、停止する必要があるレベルでキャッチアップすることです。もちろん、変数をコールスタックのずっと上までチェックする、あまり炎に値しない方法は別として。ただし、制御フローにエラーを使用するのは... 悪い形です。
最先端を行くのであれば、コルーチン (8.6 で利用可能) がニーズを満たすかもしれません。
それ以外の場合は、そこにいるときに到達する必要があるルーチンのレベルに注意し (つまり、グローバル変数を [情報レベル] に設定)、より深いプロセスで [uplevel] をそのレベルに設定します。絶対スタック フレーム。何かのようなもの
proc need-to-be-here {} {
set ::myframe [info level]
deeper-calls
}
proc deepest-call {} {
uplevel #$::myframe {what I need to do}
}
(未テスト)