Tclの名前空間についてのうんちく

わかりづらいので、普通の使い方だけにしておけば とりあえず安心でしょう。

$Id$


namespace(名前空間)とは?

proc や変数が属する階層のようなもの。 同じ x でも ::x (大域) と ::hoge::x (名前空間::hogeに属す)では別物として扱われる。 定義する段階では単に"::"が含まれる名前とあまり違いがないような。

例:

::set x 0
必ず大域の set コマンドが呼ばれる。
set x 0
現在の名前空間のsetが呼ばれる。なければ上の階層へ探しにいく(溯る)
proc ::http::hoge {} {}
::http::hoge という名のprocを定義する。 (名前空間 http である、というのはこの段階では字面上は あまり関係ない?)

何に使うん?

とりあえず新しい関数なんかは名前空間に押し込んでしまえば、他の関数名と ぶつかる心配はなくなる。 階層を溯って探す機能があるので、継承ごっこも可能。

名前空間の変更

明示的な変更

namespace eval namespace {command ...}
Pascalの use みたいなものですか。

暗黙の変更

特定の名前空間に属するprocはその名前空間で実行される。

ex. ::hoge というproc は 名前空間"::"(大域。global context)で実行される。
ex. ::noge::hoge というproc は 名前空間"::noge"で実行される。

ただし変数に関してはvariable宣言しておかないと、::noge::hoge中といえども ただの"x"はローカル変数のまま。

"set x 0"では、どこの変数が 0 になる?

従来のTclでは、

これに が加わる。 [絵がほしいね]

variable コマンドって?

global の名前空間版。

あらかじめ namespace eval ::hoehoe {variable x} としておくと、 溯るのが防がれるため、::x が存在していても namespace eval ::hoehoe {set x} はエラーになる。 (namespace eval内のvariableの効果ってこれくらいか〜?)

いきなり namespace eval ::hoehoe {set x 0} とすると、 ::hoehoe::x がセットされる。(なんでだろー)

set ::x 1 の後に上を実行すると、::x が 0 になる。

(後者は旧来のTclでの upvar ::hoehoe::x x と同じような解釈が可能)

proc内でnamespace evalった場合はproc直下ではなくnamespace eval の挙動に従う。

namespace eval 内で variable ::hoehoe::x としても、 以後 "x" が ::hoehoe::xになるわけではない。 (ローカル変数が存在しないコンテキストだから) 単に::hoehoe::xを予約する意味をもつだけ。
なお、「未定義のまま予約する」というのはsetではできない。variableでしかできない芸当。

global宣言と同じで、proc内でvariable宣言していないものはローカル変数なので、 proc脱出後は消えてしまう。 ::hoehoe::proc1 内は確かに 名前空間::hoehoeで実行されるのだが、 明示的に variable x としてやらないと "x" は ::hoehoe::x にならない。
proc ::hoehoe::proc1 {] {set x 0} は、 ::hoehoe::xが存在していてもローカルに代入される。

なお、globalコマンドと違い、 variable name ?value? なので、variable x y とすると ::hoehoe::x に "y" が代入される。

なお、変数ではなく proc については、ローカルもくそもないので 常に現在の名前空間から検索される。なければ遡って探す。

パズル:

	proc ::hone::a {} \
	{
		namespace eval ::hoehoe {
			variable ::hone::xx
			set xx 342
		}
	}
	::hone::a
とすると、どこのxxに代入されるでしょうか?

([A] ::hoehoe::xx。::hone::xxは予約されるだけ)

わかりづらいなぁ

わたしもそー思います。 深く考えてはいかんのかも。

とりあえず、

んじゃupvarの名前空間版てある?

variableコマンドで可能。

::x て書けば常に大域?

yes. 頭の"::"は絶対パスのような意味になる。 従ってglobalコマンドは不要といえば不用になる。 (global x == variable ::x)

namespace eval :: て、uplevel #0 と同じ?

たぶん。

globalもvariableもしてない変数は何になる?

proc内ならローカル変数。

それ以外なら基本的にはその名前空間に属する変数。なければ上の名前空間へ探しにいく。 この溯り検索(LISP用語でええと…なんて言ったっけ…)は、proc直下では行われない。

ではローカル変数を明示的に参照する絶対名前空間表記は?

ないみたい。([namespace current]::変数名 は(常に)ローカル変数ではない)

すると (proc内で) set y 0; variable y; とすると最初の y (ローカル変数)はアクセスできない?

それ以前に、variable y の時点で「すでにyはあるでよ」エラーになる。

名前空間はコマンドをまたぐ?

(i.e 名前空間 ::hoehoe から hoge を呼ぶと、hogeの中は::hoehoe内で実行されるのか?)

またがない。

同じprocはどう起動しても同じ名前空間で実行される。 つーかそのprocの属している名前空間で実行される。
…proc呼び出しは常にfully-qualified namespace nameに展開できるから、 どの名前空間で実行されるかも明確に決められる。
(一般にはNo。ただしhoge==::hoehoe::hogeならYes。)


kabe@sra―tohoku.co.jp