Tcl で多重代入 [Tcl]
Perl をはじめとする多くのスクリプト言語には多重代入 [1] の機能がある。例えば以下は Perl プログラマなら絶対に書いたことがある定石コードだ。
($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
Tcl の set コマンドにはこんな風に複数の変数に1回で代入する機能は無い。でもそうした構文を新たに作るのはそんなに難しいことではない。多重代入を可能にするコマンドを let コマンドと名付けてみよう。
proc let {vars vals} {
for {set i 0} {$i < [llength $vars]} {incr i} {
set var [lindex $vars $i]
set val [lindex $vals $i]
uplevel 1 set $var $val; # set $var $val ではダメ
}
}
そうするとこんな風に書ける。
% let {a b} {12 34} % puts "$a $b" 12 34
このコマンドは第1引数 vars で変数のリストを受け取って第2引数 vals で代入する値のリストを受け取る。繰り返しは見てのとおりだがその中で単に set を使って渡された変数名に代入しても上手く行かない。これは当たり前で Tcl では局所変数のスコープはプロシージャの中だからだ。ここでのトリックは uplevel コマンドを使うことである。
uplevel 1 args とするとコマンド args は「1レベル上のコンテキストで」実行される。だからここでは set コマンドがあたかも let コマンドの呼び出し元で実行されたかのような意味になるわけだ。
ところでこのコマンドの第1引数はリストなので当然要素数が1のリストでもよい。
% let a 123 % puts $a 123
しかし以下のような例では set コマンドの代替にはならない。
% let a "hello world" % puts $a hello % set a "hello world" hello world % puts $a hello world
Tcl ではスペースで区切られた文字列はリストとして解釈される。なので上の例では第1要素の hello が変数 a に代入されるだけになってしまうのだ。
コメント 0