upvar命令如何在TCL中工作?

12 tcl upvar

我在TCL中有关于upvar命令的问题.使用upvar命令,我们在其他过程中引用了全局变量或局部变量.我看到了以下代码:

proc tamp {name1 name2} {
    upvar $name1 Ronalod
    upvar $name2 Dom 
    set $Dom "Dom"
}
Run Code Online (Sandbox Code Playgroud)

这个过程被称为tamp name1 name2,并且没有全局变量name1,name2在它之外定义,这个upvar在这种情况下是如何工作的?

Don*_*ows 16

调用时upvar 1 $foo bar,它会在调用者的作用域中找到名称在foo变量中的变量,并将局部bar变量作为其别名.如果变量不存在,则以未设置状态创建(即,变量记录存在但没有值.实际上,实现使用a NULL来表示该信息,这就是Tcl没有NULL等价的原因; NULL表示非-existence)但仍然创建了链接.(它只会在本地范围被破坏时被拆除,或者upvar用于将局部变量指向别的东西.)

因此,让我们看看你的代码是什么真正做:

proc tamp {name1 name2} {
    upvar $name1 Ronalod
    upvar $name2 Dom 
    set $Dom "Dom"
}
Run Code Online (Sandbox Code Playgroud)

第一行说,我们正在创建一个名为命令tamp的程序,这一程序将有两个强制性的形式参数,而这些参数被称为name1name2.

第二行表示我们在调用者中绑定一个变量名(1来自我之前解释的级别指示符是可选的,但在惯用代码中强烈建议),该name1变量由变量(即,过程的第一个参数)给出局部变量Ronalod.从此以后,对该局部变量的所有访问(直到堆栈帧的生命结束)将实际对调用者中的绑定变量执行.

除了name2(第二个参数)和Dom(局部变量)之外,第三行几乎相同.

第四行实际上非常时髦.它读取Dom变量以获取变量名称(即,在过程调用的第二个参数中命名的变量)并将该命名变量设置为该值Dom.请记住,在Tcl中使用$阅读,从一个变量,而不是谈论变量.

过程调用的结果将是其正文中的最后一个命令的结果(即,文字Dom因为它set产生变量的内容作为其结果,它刚刚分配的值).(最后一行完全没有意义,因为它只是程序体的结束.)

调用此命令的最终结果实际上将是几乎什么都没有,除非第二个参数的名称包含一个variable RonalodDom.这太令人困惑了.当然,令人困惑的一点是set用变量第一个参数来说真的很时髦.(这几乎总是一个坏主意;它是坏代码气味的一个指标.)如果你使用它,事情本来会更简单:

set Dom "Dom"
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Dom耦合到的变量(即,由过程的第二个参数命名的变量)将被设置为Dom; 变量实际上是通过引用传递的.这个额外的东西$有很大的不同!