いいえ、そうではありません。名前空間と呼び出しフレームは、まったく異なる概念です。名前空間は、シノニムを明確にすることができる名前の階層構造です。プログラムで3 つの変数に名前foo
を付ける場合がありますが、それらを異なる名前空間に配置しても衝突しません。名前空間は、変数名とコマンド名の両方に使用できます。名前空間の内容で作成されるとnamespace eval
、それを呼び出すまで常にアクセスできますnamespace delete
。
コール スタックは、一連のスタック フレームです。最初のスタック フレーム #0 は常に存在します。コマンドが呼び出されるたびに、他のスタック フレームが作成されます (これは主に、ユーザー定義の手順であるコマンドに当てはまります。「組み込み」コマンドは独自の規則に従います)。コマンドが戻ると、それらは再び破棄されます。したがって、コマンド A を呼び出し、A がコマンド B を呼び出し、B がコマンド C を呼び出すと、コール スタックは次のようになります。
#3 : <C's variables>
#2 : <B's variables>
#1 : <A's variables>
#0 : <global and namespace variables>
を使用しない限り、各スタック フレームは、そこで作成された変数またはそこにインポートされた変数のみにアクセスできるという意味でスコープですupvar
。他のすべては隠されています。ほとんどのプログラミング言語では、グローバル スコープなどの外部スコープからの名前は、内部スコープから自動的にアクセスできます。Tcl ではそうではありません。
you を使用upvar
すると、コマンドが独自のスタック フレームの外にあるものを見ることができます。たとえば、C は を使用upvar #0 foo bar
しbar
てグローバル変数のエイリアス ( ) を作成したり、B のスタック フレーム内の変数のエイリアス ( ) を作成するために (# なしで注意) をfoo
使用したりできます。upvar 1 baz qux
qux
baz
このuplevel
コマンドを同じ行で使用して、グローバル スタックを含む別のスタック フレームでスクリプトを実行できます。実行中、スクリプトはそのスタック フレーム内のすべてのものにアクセスできますが、uplevel
呼び出し元のスタック フレーム内の変数を含め、それ以外にはアクセスできません。
::abc::def
C はを使用して名前空間変数のエイリアスを作成することもできますupvar #0 ::abc::def ghi
が、それを行わず、namespace upvar ::abc def ghi
代わりに使用してください。
代わりに、グローバル変数をインポートするためにupvar #0 foo foo
使用できます。global foo
名前空間で定義されたコマンド内で、コマンドvariable
は同じ名前空間で定義された変数をインポートできます。
これは、#0 (グローバル フレーム) または 1 (呼び出し元のフレーム) へまたは #0 への挿入にupvar
役立つことがよくあります。uplevel
他のフレーム番号を使用するとエラーが発生しやすくなり、通常は設計が不十分であることを示しています。この呼び出しにより、同じスタック フレーム内に変数 ( )upvar 0 foo bar
のエイリアス ( ) が作成されます。これは驚くほど便利です。bar
foo
処理中のイベントによって呼び出されるコマンドは、グローバル レベルを使用してコール スタックの外部で実行されます。それらがアクティブなスタック フレーム内に到達し、そこに存在する変数にアクセスする方法はありません。
簡単なデモンストレーション:
namespace eval ::abc {
variable def 42
proc xyz {} {
variable def
}
}
set foo 1138
proc A {} {
B
}
proc B {} {
set baz 1337
C
}
proc C {} {
upvar #0 foo bar
puts $bar
upvar 1 baz qux
puts $qux
namespace upvar ::abc def ghi
puts $ghi
}