TCL漫谈——upvar命令
上一篇 /
下一篇 2009-04-29 00:31:41
/ 个人分类:TCL
核心是调用栈(call stack frame)的访问
我的理解。核心是调用栈(call stack frame)的访问。
stack frame可以理解为程序执行的环境(context)。当调用一个函数时,可以认为是在当前的frame里新建了一个stack frame,函数在这个新建的frame里执行,默认情况下它能访问到的变量也局限于这个frame。要访问这个frame之外的变量,有两种思路。
- 在当前frame中通过某种声明,从而可以直接使用这个变量。这可以通过"upvar"做到。
- 将要访问这个变量的代码放到变量所在的frame执行。这可能通过"uplevel"做到。
这就要告诉程序要访问某个特定frame的位置。比如下面的例子。
uplevel #0 {puts $var_name}
uplevel #1 {puts $var_name}
uplevel 1 {puts $var_name}
uplevel 2 {puts $var_name}<br>
其中#0, #1 是stack frame绝对位置。#0表示最顶层,也就是所谓”全局“那一层。第三行,第四行的1,2表示当前frame的上一层frame,和再上一层frame。上面的例子都表示在指定的stack frame时执行相应的命令,其中变量"var_name"也应该是声明在相应的frame里的。
/××××××××××××××××××××××××××××××××××××××××××××××
//gongxing:这里说得很透彻了,我很容易联想到upvar语法:
//upvar ?level? otherVar myVar ?otherVar myVar ...?
//里的level参数跟上面一样
//1:表示当前frame的上一层frame
//2:表示再上一层frame。
//所以编写下面代码验证
××××××××××××××××××××××××××××××××××××××××××××××/
proc three {y} {
upvar 1 $y z ;# tie the calling value to variable z
upvar 2 x a ;# Tie variable x two levels up to a
puts "three: Z: $z A: $a" ;# Output the values, just to confirm
set z 1 ;# Set z, the passed variable to 1;
set a 2 ;# Set x, two layers up to 2;
}
proc two {y} {
upvar $y z ;# This ties the calling value to variable z
puts "two: Z: $z" ;# Output that value, to check it is 5
three z ;# call proc two, which will change the value
}
proc one {y} {
set x "ok"
two y
puts $x
}
set y 5
one $y
//gongxing:y和z是层层引用,而x和a是上一层的上一层引用(蓝色部分),比对结果,three函数里的a引用到了one里的x,并
//改变了x的值
"uplevel"的用法简单来说也就是如此。"upvar"则是把指定frame里的变量拿到当前frame里来用。比如:
upvar 1 var_name_outside
var_name_inside
通过这样的声明之后,当前frame里访问变量"var_name_inside"实质上就是访问上一层frame里的变量"var_name_outside"。这跟C语言中的引用很类似。
说到这里,我们再看下面两条语句:
global var_name
upvar #0 var_name var_name<br>
它们是不是有着相同的作用呢。但global很大程度上要求你必须知道变量的名字,而upvar则不需要。比如自己写一个printvar的命令的话。
# This does not work!
proc printvar_global {var_name} {
global $var_name
puts $var_name
}
# This works!
proc printvar_upvar {var_name} {
upvar #0 $var_name name
puts $name
}
这个例子可以很好的说明upvar的妙处来。
收藏
举报
TAG: