プロシジャ

プロシジャは、引数付きの関数と言った方がわかりやすいかもしれません。
プロシジャは、よく使うコマンドをまとめて関数にするための機能です。
プロシジャは、Tclコマンドと同様の振る舞いをするので、Tclコマンドと同様に使うことができます。

プロシジャ名の規則は以下の様になっています。

プロシジャの引数と返り値

以下はプロシジャの例です。
maxプロシジャは、引数で与えた2つの値の大きい方の値を返します。

proc max {a b} {
    if {$a > $b} {
        return $a
    } else {
        return $b
    }
}
max 10 20
=> 20
max 20 10
=> 20

引数は、リスト形式で列挙します。
returnコマンドは、プロシジャから値を返す時に使います。

次の例は、引数で与えた3つの値の平均を求めています。

proc average {a b c} {
    set sum [expr $a + $b + $c]
    expr $sum / 3
}
average 10 20 30
=> 20

setコマンドで作成した変数sumは、プロシジャの外から参照できないローカル変数になります。
ここでは、returnコマンドを使っていませんが、 プロシジャ内で最後に実行したコマンドの結果は、
プロシジャの返り値になるので、returnコマンドを省略できます。

引数なしのプロシジャ

プロシジャに引数がない場合は、空のリストになります。
以下の例は、現在の日付を返します。

proc getdate {} {
    set sec [clock seconds]
    clock format $sec -format "%Y/%m/%d"
}
getdate
=> 2001/09/15

グローバル変数の参照

プロシジャ内でグローバル変数を参照する場合は、global宣言をする必要があります。
以下の例は、Tclバージョンを調べて国際化に対応した版かどうかをチェックします。

proc isI18N {} {
    global tcl_version
    expr $tcl_version > 8.0
}
isI18N
=> 1

Tcl8.0以上では、globalコマンドを使わなくてもスコープ解決演算子(::)を使ってグローバル変数を参照できます。

proc isI18N {} {
    expr $::tcl_version > 8.0
}
isI18N
=> 1

可変個の引数

プロシジャに可変個の引数を渡すこともできます。
最後の引数にargsを使うと、リスト型の変数として扱うことができます。
以下の例は、引数で渡した値の合計を求めます。

proc sum {args} {
    set sum 0
    foreach num $args {
        incr sum $num
    }
    return $sum
}
sum 1 2 3
=> 6
sum 1 2 3 4
=> 10

デフォルト引数

引数に既定値を指定することで、プロシジャの呼び出し側で引数を省略できます。
以下の例は、引数で渡した2つの値の加算をします。第2引数を省略すると1が補われます。

proc add {a {b 1}} {
    expr $a + $b
}
add 10
=> 11
add 10 2
=> 12

引数の参照渡し

引数に値を渡す代わりに、変数名を渡せると便利なことがあります。
例えば、配列変数は値として渡せないので、配列変数名を渡せると便利です。
以下の例は、配列変数aryの名前を引数で渡しています。

set ary(名前) 太郎
set ary(歳) 2歳
set ary(性別) 男
proc getname {a} {
    upvar $a var
    return $var(名前)
}
getname ary
=> 太郎

upvarは、変数名の参照(別名)を作成します。

また、引数に変数名を渡すことにより、変数の値を直接書き換えることができます。
以下の例は、第1引数で渡された変数名の値を直接書き換えています。

proc add {a {b 1}} {
    upvar $a var
    set var [expr $var + 1]
}
set a 1
add a
=> 2
set a
=> 2

addプロシジャの呼び出し後に、変数aの値が2になっていることに注目してください。