Namespace

ReferenceTOPKeywords

コマンド名

namespace  - コマンドと変数の文脈を作成し、操作します。

構文

namespace ?option? ?arg ...?

解説

namespaceコマンドはコマンドと変数のために個別の文脈を作成したり、アクセスしたり、破棄したりするために使用されます。 ネームスペースに関する簡単な概要はNAMESPACEとはを参照してください。 有効なoptionは以下にリストします。 optionは省略形が使用できることに注意してください。

namespace children ?namespace? ?pattern?
namespace code script
namespace current
namespace delete ?namespace namespace ...?
namespace eval namespace arg ?arg ...?
namespace exists namespace
namespace export ?-clear? ?pattern pattern ...?
namespace forget ?pattern pattern ...?
namespace import ?-force? ?pattern pattern ...?
namespace inscope namespace arg ?arg ...?
namespace origin command
namespace parent ?namespace?
namespace qualifiers string
namespace tail string
namespace which ?-command? ?-variable? name
namespace children ?namespace ? ?pattern?
ネームスペース namespaceに属するすべての子ネームスペースのリストを返します。 namespaceが指定されない場合、現在のネームスペースの子が返 されます。本コマンドは完全に修飾された名前を返します。これは::で始まります。オプショナルなpatternが与えられると、本コマンドはglobスタイルのパターンにマッチする名前だけを返します。 使用される実際のパターンは次のように判定されます。 ::で始まるパターンはそのまま使われ、そうでなければネームスペースnamespace(あるいは現在のネームスペースの完全に修飾された名)がパターンの前に付け加えられます。

namespace code script
後のスクリプトscriptの実行のために現在のネームスペースの文脈を捕捉します。 これはscriptnamespace codeコマンドの中に包み込まれた新しいスクリプトを返します。新しいスクリプトは2つの重要なプロパティを持ちます。 第一に、それはいかなるネームスペースでも評価され、scriptを現在のネームスペース(namespace codeコマンドが呼び出されたもの)で評価させます。第二に、追加的な引数が結果 のスクリプトに追加され、 scriptに追加的な引数として渡されます。例えば、ネームスペース::a::bでコマン ド set script [namespace code {foo bar}]が呼び出されたとしたら、eval "$script x y"はいかなるネームスペースで実行できます (script の値が適切に渡されていることを仮定しています)。コマンドnamespace eval ::a::b {foo bar x y}と同じ効果を持ちます。 このコマンドは必要です。なぜなら、Tkのような拡張がグローバルネームスペースで普通 にコールバックスクリプトを実行するからです。 スコープされたコマンドはコマンドをそのネームスペース文脈と共ににそれが後で適切に実行されることを可能にする方法で捕捉します。 どのようにこれがコールバックスクリプトを作成するために用いられるかの例題はセクションSCOPED VALUESを参照してください。

namespace current
現在のネームスペースの完全に修飾された名前を返します。グローバルネームスペースの実際の名前は""(すなわち、空文字列)であるが、 このコマンドはプログラマの便利のためグローバルネームスペースに::を返します。

namespace delete ?namespace namespace ...?
各ネームスペースnamespaceが削除されて、そのネームスペースのすべての変数、プロシージャ、及び子ネームスペースが削除されます。 プロシージャが現在ネームスペースで実行していると、プロシージャが戻るまで存在しつづけます。しかし、ネームスペースは他のコードが名前でそれを探すのを防止するためにマークされます。 ネームスペースが存在しないと、本コマンドはエラーを返します。ネームスペース名が与えられないと、このコマンドはなにも行いません。

namespace eval namespace arg ?arg ...?
namespaceと呼ばれるネームスペースを活動的にして、その文脈においてあるコードを評価します。ネームスペースがまだ存在していなければ、作成されます。 1つ以上のarg引数が指定されると、引数はevalコマンドと同じ方法で、それぞれの間にスペースを挿んでお互いに連結されて、その結果 が評価されます。 
 
namespaceがネームスペース修飾子で始まっていると、先頭のネームスペースのどれかが存在しないと、それらは自動的に作成されます。

namespace exists namespace
namespaceが現在の文脈に正当なネームスペースである場合は1を返し、そうでない場合は0を返します。

namespace export ?-clear? ?pattern pattern ...?
ネームスペースからどのコマンドが公開されるか指定します。公開されたコマンドは後で他のネームスペースで namespace importコマンドを使ってインポートできます。ネームスペース内で定義されたコマンドとネームスペースが過去にインポートした両方のコマンドは ネームスペースに公開されることができます。コマンドはnamespace exportが実行された時で定義されている必要はありません。 各patternはglobスタイルの特別な文字を含むことができるが、ネームスペース修飾子を含むことはできません。すなわち、 パターンは現在の(公開を行う)ネームスペースのコマンドだけを指定できます。各patternはネームスペースの公開パターンのリストに加えられます。 -clear フラグが与えられると、ネームスペースの公開パターンリストはいかなるpattern引数が追加される前の空の状態にリセットされます。 patterns-clearも与えられないと、このコマンドは現在のネームスペースの公開パターンリストを返します。

namespace forget ?pattern pattern ...?
以前にインポートしたコマンドをネームスペースから削除します。 各patternは簡単なあるいはfoo::xa::b::p*のような修飾された名前です。 修飾された名前は::を含んで1つ以上のネームスペースで名前を修飾します。各qualified patternは公開しているネームスペースの名前で修飾されているそして修飾名の末尾のコマンド名内にglobスタイルの特別 な文字をもつことができます。 glob文字はネームスペース名には現れてはなりません。各simple pattern のため、異なるネームスペースからインポートされた現在のネームスペースにマッチするコマンドを削除します。各qualified patternに対して、このコマンドはマッチした公開されているコマンドを最初に見つけ出します。そしてこれらコマンドが現在のネームスペースにより過去 にインポートされたものでないか確認します。もしそうなら、このコマンドは相当するインポートコマン ドを削除します。事実上、これはnamespace importコマン ドの動作を取り消します。

namespace import ?-force ? ?pattern pattern ...?
コマンドをネームスペースにインポートします。各patternfoo::x a::p*のような修飾された名前です。それは公開しているネームスペース名を含み、修飾名の末尾のコマン ド名にglobスタイルの特別な文字をもつことができます。 glob 文字はネームスペース名には現れてはなりません。 pattern文字列にマッチし、 それらのネームスペースで現在公開されているすべてのコマンドが現在の ネームスペースに追加されます。これは現在のネームスペースに新しいコマンドを作成することで行われます。それはその元のネームスペースの公開されたコマンドを指します。 新しいインポートコマンドが呼び出されると、それは公開されているコマンドを呼び出します。インポートコマンドが既存のコマンドと衝突すると、このコマンド は通常はエラーを返します。しかし、-forceオプションが与えられると、インポー トコマンドは無言で既存のコマンドと置き換えられます。 namespace importは断片的な意味を持ちます。 つまり、 公開しているネームスペースで現在定義されている要求されたコマンドだけがインポートされます。言い換えるなら、 namespace importコマンドが実行された時点でネームスペースに存在するコマンドだけがインポートできます。後からこのネームスペースで他のコマンドが公開されても、それはインポートされません。

amespace inscope namespace arg ?arg ...?
特定のネームスペースの文脈でスクリプトを実行します。このコマンドはプログラマによって直接使われるためには実行されません。 アプリケーションがTkウィジェットのようなものに 登 録するコールバックスクリプトを作成するにnamespace codeコマンドを使ったとき、この呼び出しが無条件に生成されます。 namespace inscopeコマンドはlappend的な語義を持つこととネームスペースが既に存在していなければならないことを除いて、 namespace evalコマンドによく似ています。それは最初の引数をリストとして扱い、後ろのあらゆる引数を適切なリストの要素として 末尾に追加します。 namespace inscope ::foo a x y znamespace eval ::foo [concat a [list x y z]]に等しい。多くのコールバックスクリプトが実際に接頭語であるなら、 lappend的な語義は重要です。

namespace origin command 
インポートコマンドcommand が参照する元のコマンドの完全修飾名を返します。コマンドがネームスペースにインポートされると き、新しいコマンドがそのネームスペースで作成されます。それは公開しているネームスペースの実際のコマンドを指します。コマンドがネームスペースa, b,...,n のシーケンスにインポートされると、各順番のネームスペースが前のネームスペースからコマンドをインポートしている、このコマンドは最初のネームスペース、a、のもとのコマンドの完全修飾名を返します。 command がインポートコマンドを参照していないと、そのコマンド自身の完全修飾名が返されます。

namespace parent ?namespace ?
ネームスペースnamespaceの親ネームスペースの完全修飾名を返します。 namespaceが指定されないと、現在のネームスペースの親の完全修飾名が返されます。

namespace qualifier string 
stringの先頭のあらゆるネームスペース修飾子を返します。修飾子は::sで区切られたネームスペース名です。 文字列::foo::bar::xに対してこのコマンドは::foo::barを返し、:: に対しては空文字列を返します。このコマンドはnamespace tailコマ ンドと対照をなすものです。注 意すべきなのはネームスペース名が実際に現在定義されているネームスペースの名前であるかは確認しないことです。

namespace tail string 
修飾されている文字列の最後の単純な名前を返します。修飾子は::sで区切られたネームスペースの名前です。文字列::foo::bar::xに対して このコマンドはxを返し、::に対しては空文字列を返します。このコマンドはnamespace qualifiersコマンドと対照をなすものです。 ネームスペース名が実際に現在定義されているネームスペースの名前であるかは確認しません。

namespace which ?-commnad? ?-variable? name
nameをコマンドか変数のどちらかとして探します。そしてその完全修飾名を返します。例えば,nameが現在のネームスペースに存在せず グローバルネームスペースに存在すると、このコマンドはグローバルネームスペースの完全修飾名を返します。コマンドも変数も存在しないと、このコマンドは 空文字列を返します。variableコマンド、あるいは変数にtraceすることによって作成された変数が定義 されないと、このコマンドは変数の完全修飾名を返します。 フラグも与えられないとnameはコマンド名として扱われます。名前解析に関するルールの説明はセクションNAME RESOLUTIONを参照してください。

NAMESPACEとは

ネームスペースとはコマンドと変数の集合です。それらが他のネームスペースのコマンドや変数と妨げないことを保証にするために、これはコマンドと変数をカプセル化します。 Tclは常にこのような集合を1つ持っています。それがグローバルネームスペース(global namespace)として参照されているものです。グローバルネームスペースはすべてのグローバルな変数とコマンドを保持しています。 namespace evalコマンドは新しいネームスペースを作成します。例えば

namespace eval Counter {
    namespace export bump
    variable num 0

    proc bump {} {
        variable num
        incr num
    }
}

は変数numとプロシージャbumpを含む新しいネームスペースを作成します。このネームスペースのコマンドと変数は同じプログラムの他のコマン ドや変数とは独立されています。グローバルネームスペースにbumpという 名前のコマンドがあると、例えば、Counterネームスペースのbumpコマン ドとは異なります。

ネームスペースの変数はTclのグローバル変数に類似しています。それらはネームスペースのプロシージャの外側に存在しますが、上の例で示したよう に、variableコマンドを通じてプロシージャからアクセスできます。

ネームスペースは動的です。いつでもコマンドや変数を追加したり削除 したりできます。このため一連のnamespace evalコマンドを使ってネームスペースの中身を構築できます。例えば、以下の一連のコマンドは上で示した ネームスペースの定義と同じ効果を持ちます:

namespace eval Counter {
    variable num 0
    proc bump {} {
        variable num
        return [incr num]
    }
}
namespace eval Counter {
    proc test {args} {
        return $args
    }
}
namespace eval Counter {
    rename test ""
}

testプロシージャがCounterネームスペースに追加され、後にrenameコマンドを通して削除されていることに注意が必要です。 

ネームスペースはそれらの中に他のネームスペースを持つことができます。従って、それらは階層構造を持ちます。ネストされたネームスペースは親ネームスペースの中にをカプセル化されて、そして他のネームスペースからは干渉できません。

修飾された名前

各ネームスペースはhistory::safe::interpのようなテキストの名前を持ちます。ネームスペースがネストするので、 ネームスペースに含まれているコマンド、変数や子ネームスペースを参照するために修飾名が用いられます。区切り記号として/や.の代わりに::が使われることを除いて、 修飾名はUnixのファイルやTkのウィジェットと同様の階層構造のパス名です。 もっとも上のあるいはグローバルなネームスペースは名前""(即ち、空文字列)を持ち、::が別 名です。例として、 名前 ::safe::interp::createはグローバルネームスペース::の子であるネームスペース::safeの子のネームスペース interpのコマンドcreateを参照します。

他のネームスペースのコマンドや変数にアクセスすることを望むなら余分な文法を使わなければなりません。名前はそれらを含むネームスペースにより修飾されなければなりません。以下のようにグローバルネームスペースからCounterのプロシージャにアクセスできます。

Counter::bump 5
Counter::Reset

現在のカウントにアクセスするのは以下のように、

puts "count = $Counter::num"

1つのネームスペースが他の者を含んでいると、その要素に到達するために1つ以上の修飾子を必要とします。ネームスペースCounterを含むネームスペースFoo があると、以下のようにグローバルネームスペースからbumpプロシージャを呼び出すことができます。

Foo::Counter::bump 3

コマンドを作成や改名するときにも、修飾された名前を使うことができます。例えば、Fooネームスペースにプロシージャを加えるのは以下のようになります。

proc Foo::Test {args} {return $args}

そして、同じプロシージャを別のネームスペースに移動するのは以下のようにできます。

rename Foo::Test Bar::Test

修飾名に関してカバーするべき点がいくつかあります。ネームスペースはグローバルネームスペースを除いて空ではない名前を持っています。 ::はネームスペースの区切り記号として以外は、単純なコマンド、変数、そしてネームスペース名としては認められません。修飾名の中の余分な:は 無視されます。つまり、2つ以上の:はネームスペース区切り記号 として扱われます。修飾された変数、コマンドの名前の末尾の::は {}という名前の変数あるいはコマンドを参照します。しかし、修飾されたネームスペース名の末尾の::は無視されます。

名前解析

一般的に、変数やコマンドの名前をとるすべてのTclコマンドは修飾名をサポートします。これはset, proc, rename, interp, alias のようなコマンドに修飾名を与えることができることを意味します。 ::で始まる完全修飾名を提供すると、どのコマンド、変数、ネームスペースを意味するのかは疑いの余地がありません。しかし、名前が::で始まって いない(即ち、相対的である)と、それを見つけるためTclは固定ルールに従います。コマンドや変数の名前は常に最初に現在のネームスペースを、次にグローバルネームスペースを探すことで解析されます。一方で、ネームスペース名は常に現在の ネームスペースを探すことだけで解析されます。

次の例において、

set traceLevel 0
namespace eval Debug {
    printTrace $traceLevel
}

TclはまずネームスペースDebugで、そしてグローバルネームスペースでtraceLevelを探します。そしてコマンドprintTraceと同じ方法で探します。 変数やコマンドの名前がどちらの文脈でも見つからないと、その名前は未定義です。この点を完全に明確にするために次の例を考えてみて下さい。

set traceLevel 0
namespace eval Foo {
    variable traceLevel 3

    namespace eval Debug {
        printTrace $traceLevel
    }
}

ここでTclは最初にネームスペース Foo::DebugtraceLevelを捜します。そこで発見されないとき、Tclはそれからグローバルな ネームスペースでそれを捜します。変数Foo::traceLevelは名前解析過程中完全に無視されます。

namespace whichコマンドを、名前の解析に関するあらゆる問題点を解消するのに使用することができます。例えば、コマンド

namespace eval Foo::Debug {namespace which -variable traceLevel} 

::traceLevelを返します。一方、コマンド、

namespace eval Foo {namespace which -variable traceLevel}

::Foo::traceLevelを返します。

上で述べたように、ネームスペースは変数やコマンドの名前とは異なって探されます。ネームスペース名は常に現在のネームスペース内で解析されます。これは、例えば、 新しいネームスペースを作成するnamespace evalコマンドが新しいネームスペースの名前が::で始まっていなければ、常に子ネームスペースを現在のネームスペースに作成することを意味します。

Tclはどの変数、コマンド、ネームスペースに参照できるか制限するアクセス制御を持ちません。上の名前解析ルールで 1つの要素を解析する修飾名を与えると、その要素にアクセスできます。

variableコマンドを使ってネームスペース変数に同じネームスペース内のプロシージャからアクセスできます。 globalコマンドのように、このコマンドはネームスペース変数へのローカルリンクを作成します。 必要ならば、変数が現在のネームスペースに作成され、初期化されます。 注意すべきなのはglobalコマンドはグローバルネームスペースの変数にリンクを作成するだけです。 常に適切な修飾名でネームスペース変数を参照するのであれば、variableコマ ンドを使用する必要はありません。

コマンドをインポートすること

ネームスペースはしばしばライブラリを表すのに使われます。いくつかのライブラリコマンドは頻繁に使われるのでそれらの修飾名をタイプすることは 面倒です。例えば、BLTのようなパッケージの中におけるすべてのコマンドがBltと呼ばれるネームスペースに格納されています。 これらのコマンドには次のようにアクセスします。

Blt::graph .g -background red
Blt::table . .g 0,0

graphtableコマンドを頻繁に使うと、接頭辞Blt::無しでそれらにアクセスすることを望むかも知れません。以下のように、 現在のネームスペースにそれらのコマンドをインポートすることでこれは実現できます。

namespace import Blt::*

これはBltネームスペースからすべての公開されたコマンドを現在のネームスペース文脈に追加します。従って、以下のよ うなコードは書けます。

graph .g -background red
table . .g 0,0

namespace importコマンドはnamespace exportコマンドで公開されたネームスペースからコマンドだけをインポートすること行います。

どんな結果が引き起こされるか予測できないので、ネームスペースからすべてのコマン ドをインポートすることは大抵はよいことではありません。必要とする特定のコマンドだけをインポートした方がよいでしょう。例えば、コマンド

namespace import Blt::graph Blt::table

は現在の文脈にgraphtableコマンドだけをインポートします。

既に存在するコマンドをインポートしようとすると、エラーが発 生します。これは2つの異なるパッケージから同じコマンドをインポートすることを防止します。しかし時々(恐らく、デバッグ中に)、この制限を回避する ことを望むかも知れません。既にネームスペースに出現している新 しいコマンドをピックアップ(pick up)するためにnamespace importコマンドの再発行を望むかも知れません。このような場合、-forceオプションを使うことができます。そして既存のコマンドを静かに上書き できます。

namespace import -force Blt::graph Blt::table

いくつかの理由でインポートされたコマンドの利用を止めることを望むならば namespace forgetコマンドでそれらを削除できます。以下のように

namespace forget Blt::*

このコマンドは現在のネームスペースBltからインポートしたいかなるコマンドを検索します。 なにかが見つかるとそれらを削除します。見つからなければ何もしません。この後、Bltコマンドは接頭辞Blt::付きでアクセスしなければなりません。

以下のように公開しているネームスペースからコマンドを削除するときは

rename Blt::graph ""

そのコマンドはそれがインポートされているネームスペースからも自動的に削除されます。

コマンドを公開すること

以下のようにネームスペースからコマンドを公開することができます。

namespace eval Counter {
    namespace export bump reset
    variable Num 0
    variable Max 100

    proc bump {{by 1}} {
        variable Num
        incr Num $by
        Check
        return $Num
    }
    proc reset {} {
        variable Num
        set Num 0
    }
    proc Check {} {
        variable Num
        variable Max
        if {$Num > $Max} {
            error "too high!"
        }
    }
}

プロシージャbumpresetは公開されます。従って、それらは以下のようにCounterネームスペースからインポートする ときに取り込まれます。

namespace import Counter::*

しかし、checkプロシージャは公開されていません。このためインポート操作の際に無視されます。

namespace importコマンドはそれぞれのネームスペースで公開するよう宣言されたコマンドのみをインポートします。 namespace exportコマンドは他のネームスペースでインポートされてもよいコマンド がどれであるか指定します。 namespace importコマンドが公開されていないコマンドを指定すると、そのコマンドはインポートされません。

参照

variable

キーワード

exported, internal, variable


Copyright © 1993-1997 Bell Labs Innovations for Lucent Technologies Copyright © 1997 Sun Microsystems, Inc. Copyright © 2000 Scriptics Corporation. Copyright © 1995-1997 Roger E. Critchlow Jr.