Tcl 8.5 の dict コマンド(予告編) [Tcl]
Tcl 8.5 コマンドレビューの第3回目として dict コマンドについて見ていく。
これは名前から想像されるように連想配列を扱うためのコマンドだ。だけど Tcl には既に array という連想配列がある。何が違うのか。それを比較するためにまずは既存の array の特性について、特にその使いにくさについて復習しよう。
Tcl では array は以下のように括弧で添字を囲むよくありがちな表記法で利用できる。
% set v(1) foo foo % set v(2) bar bar % puts $v(1) foo % puts $v(2) bar
なお「(」や「)」はTclの変数名として使用が禁じられているわけではない。
% set a( 1 1 % set a) 2 2
確かに次のように変数展開をしようとすると予期しない結果になる。
% puts $a) can't read "a": no such variable
しかしこれは変数名に対する制約というよりは変数展開時の解析方法の制約である。ドル記号を使った通常の変数の置き換えでは英数字(と「_」と「::」)の続くところまでを変数名とみなすので「$a」を展開したものと「)」という文字の連続とみなされているだけだ。これは以下のような中括弧を使った記法で回避できる。
% puts ${a)} 2
ここまで読んで Tcl のミニマリズムについて聞かされた事のある人はこう思うかもしれない。なるほど、Tcl では連想配列といっても実は他の変数と同様の変数定義の束であり、単に慣習により var(index) という形の名前をとるだけとみなすことができるのではないか。
これは正しくない。まず括弧の組を使った変数の置き換えは Tcl のパーサにより特別扱いされる。括弧の中ではさらなる変数置き換えやコマンド置き換えが許される。
% set ver [info tclversion] 8.5 % set v(8.5) foo foo % puts $v($ver) foo % puts $v([info tclversion]) foo
また一度配列名として使われた名前は普通の変数としては使えなくなる。
% set v bar can't set "v": variable is array
しかし一方で Tcl の array が変数の束であるという見方が妥当だと思える点もある。array はプロシージャの引数や戻り値として受け渡しできない。
% proc take_array v { puts $v(1) } % take_array $v can't read "v": variable is array % proc return_array {} { set v(tcl) 8.5 return $v } % return_array can't read "v": variable is array
Tcl で引数や戻り値になりうるのは文字列だけであるということを思い出そう。array は全体として文字列ではないのだ。実のところこれが Tcl の EIAS ドグマと相容れるものなのかはかなり疑問である。ともかく array にはこのような使いにくさがあり、しばしば混乱を招くものだった。
では array を受け渡ししたい場合はどうすればよいのか。方法は2通りある。
ひとつは array をリストに「シリアライズ」する方法。リストは何ら後ろめたいところ無く文字列なので受け渡しできる。
% proc take_array l { array set v $l puts "v(1) is $v(1)" } % array get v 1 foo 2 bar 8.5 foo % take_array [array get v] v(1) is foo % % % proc return_array {} { set v(1) blablah return [array get v] } % return_array 1 blablah % array set r [return_array] % puts $r(1) blablah
array get は与えられた名前の配列から「添字 値 添字 値 ...」というリストを作る。array set はその逆でリストから配列に内容を設定する。
2つ目の方法はいわば「参照渡し」で、配列の名前を渡してプロシージャの中で upvar する方法だ。
% proc take_array {v} { upvar 1 $v myvar puts "myvar(1) is $myvar(1)" } % take_array v myvar(1) is foo
「upvar 1 otherVar myVar」は呼び出し元に向かって1レベル上に辿って(つまり直接の呼び出し元)、そのレベルに存在する変数 otherVar の別名を myVar とする。
以上 Tcl の既存の array の使いにくさについて書いた。それは
(1) 純粋に文字列ではない
(2) プロシージャ間で受け渡しできない
という特徴を持つ。
新たに Tcl 8.5 に導入された dict はこうした特性のかなりの部分を解消するものである。続く。
コメント 0