谁能让我知道TCLupvar 0
和upvar 1
TCL之间的区别,我们如何实时使用。请,如果有人举例解释,它会让我更清楚。
3 回答
当你调用一堆过程时,你会得到一堆堆栈帧。它在名字里。我们可以这样想象:
美国广播公司 123 456 公元前 321 456 cde 654 321
好的,所以我们有abc
callbcd
呼叫cde
。简单的。
和在查找要链接到的变量0
时说明要向上堆栈多少级。意味着上升一个级别(即,到当前帧的调用者),例如在我们的示例中从到到,将从上到一直到运行整个脚本和回调的全局评估级别。是这种情况的特例;这意味着在当前堆栈帧中进行查找。还可以通过将名称放在名称前面来使用堆栈底部的索引,因此表示全局框架,它首先调用。1
upvar
1
cde
bcd
2
cde
abc
3
0
#
#0
#1
最常见的用法upvar
是upvar 1
(如果你不考虑关卡,那就是它的作用)。upvar 0
仅当您想要为变量获取不同(通常更易于使用)名称时才真正使用。下一个最常见的是upvar #0
, 虽然global
是一个更常见的简写形式(为了方便起见,它匹配名称的非限定部分)。其他形式很少见;例如,upvar 2
通常表示代码非常混乱和纠结,upvar #1
在 Tcl 8.6 的协程之前几乎没有人使用过。我从未见过upvar 3
或从未见过upvar #2
(尽管计算的级别指标存在于 Tcl 的某些对象系统中)。
示例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
——简化变量名:
proc remember {name contents} {
global my_memory_array
upvar 0 my_memory_array($name) var
if {[info exist var]} {
set var "\"$var $contents\""
} else {
set var "\"$name $contents\""
}
}
remember x 123
remember y 234
remember x 345
remember y 456
parray my_memory_array
# my_memory_array(x) = ""x 123" 345"
# my_memory_array(y) = ""y 234" 456"
与 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
好的,我认为一个示例将使差异变得非常清楚:
假设我们有一个函数 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 上一帧。