Array的意思是“数组”,而Tcl中的array实际上被称为map更合适。Tcl中的list则实际上相当于数组。
map的主要特点是存储键值对,即一个索引对应一个值。相当于perl里面的哈希表(hash table)。
Tcl中有两种办法给array赋值:array
命令或者set
命令。
array set ta [list a 1 b 2] ; # 同时存储了两个键值对 set ta(c) 3 ; # 结果是array ta的值相当于 a=>1, b=>2, c=>3
相对应的获取array中元素值的获取也有两种办法:
set v [lindex [array get ta a] 1] ; # 注意这里使用了lindex命令 set v $ta(a)
array get
命令实际上同时返回了索引和值。这看起来好像显得有些不方便,但如果要同时处理多个元素,就会显出它的方便来了。
foreach {k v} [array get ta *] { puts [list $k $v] }
命令array get
实际上是使用通配符来匹配键值的。
如果要删除array中的某些值,可以用命令array unset name b
。这个命令同样支持通配符,因此要清空array的话,就可以用array unset *
。
如果要只获取array中所有的键值(索引),可以用命令array names *
。
如果要判断一个变量是不是array,可以用命令 array exists name
那怎么删除整个数组呢?数组的名字和普通变量的名字享有同样的命名空间,因此
unset
命令Tcl中的array是不可以用作proc的参数,也不可以作为返回值的,即下面的例子是会出错的。
array set ta [list a 1 b 2 c 3] proc f {r} { puts $r(b) array set tb [list a 3 b 4 c 5] return $tb ; # 不可以直接返回array } set rv [f $ta] ; # 不可以直接传递array作为参数
解决办法有两种,一种是利用list对array进行转换;另一种是把数组声明在函数外部(利用namespace
或者upvar
)。
proc f {r} { array set rr $r ; # list转换为array puts $rr(b) array set rr [list a 3 b 4 c 5] return [array get rr *] ; # array转换为list } array set ta [list a 1 b 2 c 3] array set rv [f [array get ta *]] ; # 利用list对arrray进行转换
proc f2 {name} { upvar $name rr ; # 映射外部变量为局部变量 puts $rr(b) uplevel [list array set $name [list a 3 b 4]] ; # 赋值到上一层frame中 } array set ta [list a 1 b 2 c 3] f2 ta ; # 传递array的名字作为参数
Tcl中允许数组的名字为空,这就构成了一个特殊的空数组。比如 set (a) 1
或者 array set :: {a 1 b 2}
。
Tcllib中用来实现面向对象(class)的stooop就利用空数组这一特性。