3

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

4

3 に答える 3

4

非ローカル リターン (つまり、いくつかのレベルをスキップして戻る) を行うコードを取得する必要がある場合は、-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 以降ではより使いやすいツールが提供されます。

于 2012-04-05T10:40:49.897 に答える
3

簡単に言えば、デザインを再考したほうがよいでしょう。

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

于 2012-04-05T00:26:44.450 に答える
1

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

それ以外の場合は、そこにいるときに到達する必要があるルーチンのレベルに注意し (つまり、グローバル変数を [情報レベル] に設定)、より深いプロセスで [uplevel] をそのレベルに設定します。絶対スタック フレーム。何かのようなもの

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

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

(未テスト)

于 2012-04-05T00:34:33.563 に答える