任何人都可以让我知道TCL中Activity
和upvar 0
之间的区别,我们如何实时使用。但是,如果有人用例子解释,它会让我更清楚。
答案 0 :(得分:10)
当你调用一堆程序时,你会得到堆栈帧的堆栈。它就在名字中。我们可能会这样想象:
abc 123 456 bcd 321 456 cde 654 321
好的,我们已abc
致电bcd
致电cde
。简单。
0
中的1
和upvar
表示在查找要链接的变量时,堆栈上升了多少级别。 1
表示向上一级(即,到当前帧的调用者),在我们的示例中从cde
到bcd
,{{1}从2
一直到cde
和abc
一直到全局评估级别,整个脚本和回调都会运行。 3
是一个特殊情况;它意味着在当前堆栈帧中进行查找。还可以通过将0
放在名称前面来使用堆栈底部的索引,因此#
表示全局帧,#0
它调用的第一个东西。
#1
最常见的用途是upvar
(如果你离开了关卡,那就是它的作用)。 upvar 1
仅在您希望为变量获得不同(通常更易于使用)的名称时才使用。下一个最常见的是upvar 0
,虽然upvar #0
是一种更常见的简写(为方便起见,它与名称的不合格部分相匹配)。其他形式很少见;例如,global
通常表示真正令人困惑和纠结的代码,几乎没有人在Tcl 8.6的协程之前使用过upvar 2
。我从未在野外见过upvar #1
或upvar 3
(虽然在某些Tcl对象系统中存在计算级别指标)。
upvar #2
的示例 - 按名称传递变量:upvar 1
proc mult-by {varName multiplier} {
upvar 1 $varName var
set var [expr {$var * $multiplier}]
}
set x 2
mult-by x 13
puts "x is now $x"
# x is now 26
的示例 - 简化变量名称:upvar 0
答案 1 :(得分:2)
与upvar 1不同,upvar 0为变量创建别名。 例如:
set a 4
proc upvar1 {a} {
upvar 1 a b
incr a 4
incr b 3
puts "output is $a $b"
}
proc upvar0 {a} {
upvar 0 a b
incr a 4
incr b 3
puts "output is $a $b"
}
upvar1 $a
puts "in global frame value of a is $a"
set a 4
upvar0 $a
puts "in global frame value of a is $a"
输出:
output is 8 7
in global frame value of a is 7
output is 11 11
in global frame value of a is 4
答案 2 :(得分:1)
好的我认为一个例子可以很明显地区别对待:
让我们说我们有一个函数test_upvar1:
proc test_upvar1 {} {
upvar 1 a b
incr b
}
一个函数test_upvar0:
proc test_upvar0 {} {
upvar 0 a b
incr b
}
现在我们设置变量a并调用这两个函数来看看会发生什么:
set a 5
test_upvar1
这将返回6
set a 5
test_upvar0
将返回1
这是因为我们选择0和1执行帧0链接在相同的执行帧1中更高的帧。