Array in Tcl

@ 2011-07-27 18:39:10
标签:

    Array的意思是“数组”,而Tcl中的array实际上被称为map更合适。Tcl中的list则实际上相当于数组。

    map的主要特点是存储键值对,即一个索引对应一个值。相当于perl里面的哈希表(hash table)。

    array 的基本用法

    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

    那怎么删除整个数组呢?数组的名字和普通变量的名字享有同样的命名空间,因此

    • array的名字不可以和其它变量的名字重复
    • 删除array也可以像普通变量那样使用unset命令

    array 用作 proc 的参数或返回值

    错误的用法

    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)。

    利用list对array进行转换

    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进行转换
    

    利用upvar或uplevel访问proc外部的array

    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的名字作为参数
    

    有趣的空数组(empty array)

    Tcl中允许数组的名字为空,这就构成了一个特殊的空数组。比如 set (a) 1 或者 array set :: {a 1 b 2}

    Tcllib中用来实现面向对象(class)的stooop就利用空数组这一特性。

    标签:

      分享到:
      comments powered by Disqus

      30/34ms