TCL中upvar 0和upvar 1之间的差异

vel*_*ian 5 tcl upvar

谁能让我知道TCL upvar 0upvar 1TCL 之间的区别,我们如何实时使用.但是,如果有人用例子解释,它会让我更清楚.

Don*_*ows 10

当你调用一堆程序时,你会得到一堆堆栈帧.它就在名字中.我们可能会这样想象:

abc 123 456
   bcd 321 456
      cde 654 321

好了,我们已经得到了abc主叫bcd通话cde.简单.

01upvar说多少级仰视变量链接到时候去堆栈.1意味着进入上一层(即,在主叫用户当前帧的),从说cdebcd在我们的例子中,2会去从cde多达abc3一路攀升到全球评价水平,整体脚本和回调运行.0这是一个特例; 它意味着在当前堆栈帧中进行查找.还可以通过放在#名称前面来使用堆栈底部的索引,因此#0指示全局框架,#1它首先调用它.

最常见的用途upvarupvar 1(如果你离开了水平,那就是它的作用).upvar 0只有在想要为变量获得不同的(通常更容易使用)名称时才会使用它.下一个最常见的一个是upvar #0,虽然global是一个更常见的简写(为方便起见,它匹配名称的不合格部分).其他形式很少见; 例如,upvar 2通常表示真正令人困惑和纠结的代码,几乎没有人upvar #1在Tcl 8.6的协程之前使用过.我从未见过upvar 3upvar #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
Run Code Online (Sandbox Code Playgroud)

示例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"
Run Code Online (Sandbox Code Playgroud)


TM9*_*M90 1

好吧,我认为一个例子可以让差异变得很清楚:

假设我们有一个函数 test_upvar1:

proc test_upvar1 {} {
    upvar 1 a b
    incr b
}
Run Code Online (Sandbox Code Playgroud)

还有一个函数 test_upvar0:

proc test_upvar0 {} {
    upvar 0 a b
    incr b
}
Run Code Online (Sandbox Code Playgroud)

现在我们设置变量 a 并调用这两个函数来看看会发生什么:

set a 5
test_upvar1
Run Code Online (Sandbox Code Playgroud)

这将返回 6

set a 5
test_upvar0
Run Code Online (Sandbox Code Playgroud)

将返回 1

发生这种情况是因为我们用 0 和 1 选择我们的执行帧 0 链接在同一执行帧 1 上一个帧。

参见http://wiki.tcl.tk/1508