Tclコマンド編

 プロシジャー
 ここでは、Tclのスクリプトを生成したりファイルから読み込んで実行したりするコマンドと、プロシジャの中で用いる主なコマンドを解説します。
 まず、プロシジャーを生成するコマンドから始めましょう。
 以下のスクリプトを実行してみてください。
 
proc proc_test1 { num } {
  if { [string length $num] == 0 || [string compare $num "0"] == 0 || \
       [catch {format %d $num}] == 1 } {
    puts "1以上の整数を入れてください"
    return -code error
  }
  set sum 0
  for {set cnt $num} {$cnt>=1} {incr cnt -1} {
    incr sum $cnt
  }
  return $sum
}
 さて、上記のスクリプトをコピー&ペーストしても、何も起こらなかったと思います。それは、「proc」コマンドが、proc_test1というプロシジャーを実行するコマンドではなく、proc_test1という名前のプロシジャーを登録するコマンドだからです。
 ここでは、Tclの重要な概念のひとつである「遅延評価」が行われています。例えば、この時点ではまだ変数num、sumなどの置換やstringコマンドは実行されません。次のようにプロシジャーを実行して初めて、内部のスクリプトが実行されます。
 
proc_test1 10
 このプロシジャーの2個所でreturnコマンドが使用されています。returnコマンドは、このように文字列を返すことだけでは無く、プロシジャーの実行状態も返すことが出来ます。後で説明するcatchコマンドを用いると、エラーか否かが分かります。そのため、これを用いれば、正常かそうでないかの判定用に引数を持たせなくてもよくなります。
 sourceコマンドは、テキストファイルを読み込んで、その内容をTclスクリプトとみなし、インタプリタに渡して評価します。Tclを用いてソフトウェアを作成する場合には、必須のコマンドと言えます。
 globalコマンドは、一見グローバル変数宣言に思えますが、実はグローバルスコープ(レベル#0)の変数へアクセスするための宣言です。例えば、上記のプロシジャーproc_test1をコンソールに入力して実行した場合、プロシジャーproc_test1は、グローバルレベルで実行されます。そして、proc_test1プロシジャー内部のスクリプト、例えば1行目の if コマンドの実行スコープはレベル#1です。
 ですから、次の例のようにグローバルスコープにsumという変数が存在しても、互いに影響を与えません。
 
set sum 10
proc_test1 $sum
set sum
 そのため、グローバル変数をプロシジャーの内部で使用する場合には、globalコマンドを用いて列挙したグローバル変数のみ、使用できるようにします。
 最後に、コマンド名を変えるrenameコマンドです。これは、変更後の名前を空文字にすると、コマンドをインタプリタから削除します。不要なプロシジャーを削除することで、メモリーを有効に使ったり、「危険」なコマンドを無効にするために用います。
 
proc proc_test2 {} {
  puts "proc_test2"
}
proc_test2
rename proc_test2 aa
aa
rename aa {}
aa
 プロシジャーを登録する。


 実行してみる。
 名前を変えてみる。
 新しい名前で実行してみる。
 プロシジャーを削除する。
 結果は?

 

  proc Tclプロシジャーを生成する。
proc name args body
name プロシジャー名。
args 引数名。複数指定する場合は、リストにする。
呼び出す際に変数を指定した場合でも、変数置換された上で呼び出されるため、
その変数には、影響を及ぼさないことに注意。
body スクリプト。
例) >proc proc_test2 {str} {
if { $abc == "ab" } {
puts "pat-1"
} elseif { $abc == "bc" } {
puts "pat-2"
} {
puts "pat-3"
}
}
>set wk abc
>proc_test1 $wk
pat-3
proc_test2というプロシジャを定義する。
以下、本体。






ここまで。
変数に文字列を設定。
プロシジャーを呼び出す。
  source テキストファイルを読み込んで、Tclスクリプトとして実行する。
最後に実行したコマンドの実行結果を返す。
後者2つの形式は、Macintoshのみ。説明は省略します。
source fileName
source -rsrc resourceName ?fileName?
source -rsrcid resourceId ?fileName?
fileName Tclスクリプトファイル名。(絶対、あるいは相対パスで指定する)
例) >source d:/bsc/tcl81b1/tmp/samp.tcl ディレクトリセパレータに注意。
  return プロシジャーから呼び出し元に返る。
return ?-code code? ?-errorinfo info? ?-errorcode code? ?string?
?-code code? 例外的リターン生成に使う。以下の通り。
ok:正常終了。デフォルト
error:エラー終了。errorInfoとerrorCode変数を設定できる。
return:呼び出し元も終了する。
break:現在のプロシージャは完了コードTCL_BREAKで 終了する。これは現在のプロシジャーを呼び出したコードのもっとも内側にネストされた ループを終了させる。
continue:現在のプロシジャーは完了コードTCL_CONTINUEで終了する。これは現在のプロシージャを呼び出したコードのもっとも内側にネストされたループの現在の繰り返しを終了させる。
value:Valueは整数でなければならない; これは現在のプ ロ シージャの終了コードとして返される。
?-errorinfo info? Tclインタプリタが管理するグローバル変数「errorInfo」に info を設定する。
?-errorcode code? Tclインタプリタが管理するグローバル変数「errorCode」に code を設定する。
?string? 呼び元に返す文字列。
例) >proc proc_test3 { opt } {
return -code $opt
}
>proc proc_test4 {} {
puts "TEST:ok"
foreach i {0 1} {
foreach j {3 4} {
puts "$i,$j"
proc_test3 ok
puts *
}}
puts "TEST:break"
foreach i {0 1} {
foreach j {3 4} {
puts "$i,$j"
proc_test3 break
puts *
}}
puts "TEST:continue"
foreach i {0 1} {
foreach j {3 4} {
puts "$i,$j"
proc_test3 continue
puts *
}}
}
>proc proc_test5 {} {
puts "TEST:value"
foreach i {0 1} {
foreach j {3 4} {
puts "$i,$j"
puts [catch {proc_test3 20}]
}}
}
>proc proc_test6 {} {
puts "TEST:error"
foreach i {0 1} {
foreach j {3 4} {
puts "$i,$j"
proc_test3 error
puts *
}}
}
>proc_test4
TEST:ok
0,3
*
0,4
*
1,3
*
1,4
*
TEST:break
0,3
1,3
TEST:continue
0,3
0,4
1,3
1,4

>proc_test5

>proc_test6

引数文字列を、-code のオプションとしてリターンするプロシジャーを登録する。
後は、それぞれのコードごとの振る舞いに注意。
  global グローバルスコープ(レベル)の変数へのアクセス宣言。
global varname ?varname ...?
varname 変数名。複数の場合は、空白文字で区切って記述すること。
例) >set val 10
10
>proc proc_test7 {} {
global val
puts "val=$val"
}
>proc_test7
val=10
>proc proc_test8 {} {
set val 20
puts "val=$val"
}
>proc_test8
val=20
>set val
10
グローバル変数 val に、10を設定する。

グローバル変数の、val を表示する。





ローカル変数の、val を表示する。





グローバル変数には、影響しない。
  rename コマンドの名前の変更、または削除。
rename oldName newName
例) >proc proc_test9 {} {
puts "proc_test9"
}
>proc_test9
proc_test9
>rename proc_test9 {}
>proc_test9
invalid command name "proc_test9"
プロシジャーを登録する。


実行してみる。

削除する。
実行してみると、...
存在しない。