SSブログ

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 に代入されるだけになってしまうのだ。

[1] http://pub.cozmixng.org/~the-rwiki/rw-cgi.rb?cmd=view;name=%A5%B9%A5%AF%A5%EA%A5%D7%A5%C8%B8%C0%B8%EC%A4%CE%C8%E6%B3%D3%3A%3A%C2%BF%BD%C5%C2%E5%C6%FE


nice!(0)  コメント(0)  トラックバック(0) 
共通テーマ:パソコン・インターネット

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。