1. upvar:类似于C语言中的引用传参(别名)
这里涉及到层级(栈级)的概念,upvar 2表示向上两级,默认值是1.
我们知道局部变量(函数参数)都是存在栈中的,这样做就是将栈进行分级,便于访问变量,只要切换到变量所在的栈级,就可以访问到它了。
使的在函数内部可以更改函数外部的变量的值
% set a 10 ;#定义一个变量a,值为10
10
% proc test {x} {puts $x
}
% test a
a
% test 10
10
% proc fun {x} {upvar $x y ;#y对应的是字符串x所对应的变量的值,指向变量xputs $xputs $y
}
% fun a
a
10
% fun 10
bad level "10"
2. 再看一个例子
% namespace eval foo {namespace export funproc fun {} {upvar 1 name jset j "book"}
}
% set name "yan"
yan
% puts $name
yan
% foo::fun
book
% puts $name
book
1)namespace export fun:表示fun函数可以在外部调用,还可以用namespace import 导入到另一个namespace。
2)upvar后的1表示层级,如果不指定,它会使用上一级,默认值是1,还可以使用抽象的层级号码,形式是#后接一个层级数字。
3)upvar name j : 用j引用name,改变j的值就相当于改变name的值。
3. 层级
% proc fun {} {puts "fun: [info level]";too;};
% proc too {} {puts "too: [info level]";bar;}
% proc bar {} {puts "bar: [info level]"}
% puts "global: [info level]"
global: 0
% fun
fun: 1
too: 2
bar: 3
从上面可以看出预设的最外一层global的层级是0,fun的层级是1,fun内调用too是2,too内调用bar是3.
若想在bar中存取fun级,fun是bar的上两级,应该使用uplevel 2 { }。
最后一个例子
% proc test {x} {puts "test level = [info level]"upvar 2 $x myxputs "test::x $x"puts "test::myx $myx"
}
% proc fun {x} {puts "fun level = [info level]"upvar 1 $x funxputs "fun::x $x"puts "fun::funx $funx"test b
}
定义了两个proc,下面来调用:
% set a 10
10
% set b 20
20
% fun a
fun level = 1
fun::x a
fun::funx 10
test level = 2
test::x b
test::myx 20