SSブログ

Tcl 8.5 の dict コマンド(本編) [Tcl]

一つ前の記事では Tcl の array が全体として文字列ではなく、従ってプロシージャ間でそのまま値としては受け渡せないということを見た。

Tcl 8.5 で導入された dict は辞書に対する操作を提供するコマンドである。辞書とは前回の記事で「array をシリアライズしたリスト」といっていたものに相当する。

キーから値を取り出す dict get は以下のように使える。

% dict get {key1 value1 key2 value2} key1
value1
% dict get {key1 value1 key2 value2} key2
value2

array とは異なり辞書は通常のひとつの変数にそのまま収まり、かつそのまま dict コマンドで操作できる。

% set d1 {key1 value1 key2 value2}
key1 value1 key2 value2
% dict get $d1 key1
value1
% dict get $d1 key2
value2

キーに対応する値を設定する場合は dict set を使う。辞書が dict コマンドにより操作された場合の順序性は保証されない。

% dict set d1 key3 value3
key3 value3 key1 value1 key2 value2
% dict set d1 key3 value_three
key3 value_three key1 value1 key2 value2

そのほか各種ユーティリティコマンドが dict のサブコマンドとして提供されている。
array との違いで興味深いのは辞書はネストできるという点だ。array はネストできない。次のコマンドは一見動くように見える。

% set a(1)(2) a
a

だが騙されてはいけない!

% array names a
1)(2

Tcl の array で二次元配列のようなことをする場合は a(1,2) のような記法を使用するのが普通で、この「1,2」のコンマは単なる慣例である。

一方、先の dict set は実はキーを複数とることができて、その場合ネストされた辞書に対する操作とされる。

% dict set d2 lv1 lv2 value
lv1 {lv2 value}

これは辞書 d2 の lv1 キーに対応する値が辞書であり、その内側の辞書の lv2 キーに対応する値が value であるということになる。

dict get も同様に複数のキーを取れる。次の例の2つ目のコマンドは3つ目と等価だ。

% dict get $d2 lv1
lv2 value
% dict get $d2 lv1 lv2
value
% dict get [dict get $d2 lv1] lv2
value

ところでこの「lv1 {lv2 value}」というのはインタラクティブシェルの pretty printing の結果ではなく、あくまでそのまま文字列として扱えるものだということに注意したい。

% regsub -all { } $d2 _ s
2
% puts $s
lv1_{lv2_value}
% append d2 { newkey newvalue}
lv1 {lv2 value} newkey newvalue
% dict get $d2 newkey
newvalue

さて、前回解説したように array にはプロシージャ間で受け渡しができないという問題点があった。dict は文字列である。文字列は受け渡しできる。

% proc take_dict v {
        set a [dict get $v 1]
        puts "$a"
}
% set d3 {1 one 2 two}
1 one 2 two
% take_dict $d3
one
% proc return_dict {} {
        return [dict create 1 one 2 two]
}
% set r [return_dict]
1 one 2 two
% dict get $r 1
one
% dict get $r 2
two

dict の導入は Tcl にパワフルな機能をもたらすものだ。連想配列に極めて広範囲な利用法があるということについては Lua に例がある。そして Tcl 哲学の「すべては文字列である」と結びつくことでさらなる可能性が開ける。例えば文字列である辞書はそのままファイルに永続化してそのままロードできる。

% set f [open tmp w]
file9f5098
% puts -nonewline $f $d3
% close $f
% type tmp; # Unix なら cat
1 one 2 two%
% set f [open tmp]
filea0f5b8
% set d4 [gets $f]
1 one 2 two
% close $f
% dict get $d4 1
one
% dict get $d4 2
two

Programming in Lua の12章には Lua のテーブルを Lua コードとして永続化してそのコードを走らせることで再利用する技法が紹介されているが、Tcl のこの方法はそれよりもはるかに平明だ。


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

nice! 0

コメント 0

コメントを書く

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

トラックバック 0

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