プロシージャの名前空間 - 2023.2 日本語

Vivado Design Suite ユーザー ガイド: Tcl スクリプト機能の使用 (UG894)

Document ID
UG894
Release Date
2023-11-17
Version
2023.2 日本語

デフォルトでは、Tcl インタープリター内で作成されたプロシージャはグローバル名前空間内に作成されます。この欠点は、異なるソースからの複数の Tcl スクリプトが使用される場合に、プロシージャ名または変数名の競合が発生する可能性があることです。また、一部のプロシージャのみで使用される、ユーザーが直接アクセスすることを意図しないプロシージャが、グローバル名前空間に含まれることになる可能性もあります。

Tcl では、すべての変数およびプロシージャをグローバル名前空間内で定義する代わりに、範囲を制限した変数およびプロシージャを含む名前空間がサポートされています。名前空間はネストさせることができ、範囲のレベル数の制限なしで、名前空間内に別の名前空間を定義できます。名前空間は、プロシージャ名および変数名に新しい構文を追加します。2 つのコロン (::) で、変数名またはプロシージャ名と名前空間名を区切ります。

次の例に、名前空間の作成方法とその名前空間にプロシージャおよび変数を割り当てる方法を示します。この例では、2 つのパブリック プロシージャ (foo および push) を含む小さなスタックの機能を再生する名前空間 pop を作成しています。

01 namespace eval foo {
02  variable stack [list]
03  variable count 0
04  variable params
05  array set params [list var1 value1 var2 value2 var3 value3]
06  
07  namespace export push pop
08  
09  proc push { args } {
10   variable stack
11   variable count
12   lappend stack $args
13   incr count
14  }
15 
16  proc pop {} {
17   variable stack
18   variable count
19   if {[llength $stack] > 0} {
20    set value [lindex $stack end]
21    set stack [lrange $stack 0 end-1]
22    incr count -1
23    return $value
24   } else {
25    error " no more element in the stack"
26   }
27  }
28  
29 }
30 
31 proc foo::dump {} {
32  variable stack
33  variable count
34  if {[llength $stack] > 0} {
35   puts " There are $count element(s) in the stack:"
36   foreach element $stack {
37    puts "  $element"
38   }
39   return 0
40  } else {
41   error " no element in the stack"
42  }
43 }
44 
45 namespace import foo::*

説明:

  1. 次のコマンドを使用して名前空間を定義します。
    namespace eval <name> { … }
    
  2. 行 1 は名前空間 foo を定義し、行 29 は名前空間定義の閉じかっこです。
  3. 名前空間内の変数は、variable コマンドで作成します (行 2 ~ 4)。
    variable <varname> ?<varvalue>?

    Tcl 配列を variable コマンドで初期化することはできません。まず作成し (行 4)、その後で初期化する必要があります (行 5)。

    注記: 名前空間内で変数を定義するのに set コマンドを使用しないでください。そのようにすると、グローバル名前空間に同じ変数名がある場合に Tcl インタープリターで混同される可能性があります。
  4. プロシージャは、名前空間定義の中または外に作成できます。コマンド namespace eval … { … } 内でプロシージャを作成した場合、名前に名前空間の修飾子 (この例では foo::) は必要ありません。

    行 9 および 16: 名前空間定義内に push および pop を作成します。

  5. プロシージャを名前空間定義外で作成し、プロシージャ名に完全な名前空間修飾子を付けて名前空間に追加することもできます。上記の例では、プロシージャ dump を名前空間定義外で作成し、名前空間 foo に追加しています (行 31)。
  6. 行 10~11、17~18、32~33: プロシージャで、キーワード variable を使用して名前空間内で作成された変数を参照します。
  7. 名前空間内で作成されたプロシージャは、完全な名前空間修飾子 (foo::pushfoo::popfoo::dump など) を使用してアクセスできます。同じ名前空間内のプロシージャを参照する場合は、名前空間修飾子は必要ありません。たとえば、dump プロシージャで push を呼び出す必要がある場合、foo::push ではなく push を指定します。
  8. 行 7: 名前空間では、パブリックおよびプライベート プロシージャという概念がサポートされます。名前空間内のすべてのプロシージャは完全な名前空間修飾子を使用してアクセスできますが、コマンド namespace export… を使用すると、どのプロシージャを名前空間外にエクスポートするかを指定できます。プロシージャ名をエクスポートすると、コマンド namespace import… (行 45) を使用してグローバル名前空間にインポートできます。このようにすると、プロシージャを完全な名前空間修飾子を指定せずに直接呼び出すことができるようになります。

    次に、名前空間 foo の使用例を示します。

    vivado% foo::push This is a test
    1
    vivado% foo::push {This is another line}
    2
    vivado% push This is the third line
    3
    vivado% foo::dump
     There are 3 element(s) in the stack:
        This is a test
        {This is another line}
        This is the third line
    0
    vivado% puts "The last element stacked is: [foo::pop]"
    The last element stacked is: This is the third line
    vivado% puts "The previous element stacked is: [pop]"
    The previous element stacked is: {This is another line}
    vivado% foo::dump
     There are 1 element(s) in the stack:
        This is a test
    0
    vivado% dump
    invalid command name "dump"