tcl 中的 upvar 和全局命令之间有什么实际区别
我对 TCL 相当陌生,正在为其他人开发的一些代码提供质量保证(不是真的!)。 在这个特定的程序中有很多很多的全局变量,我有时会看到 upvar 被使用,通常与 global 结合使用。 我知道 upvar 模拟引用传递,但是以下两个过程之间的实际区别是什么?
set myBigFatGloblVariable "hello"
proc myFirstProc { var1 var2 } {
upvar 1 $var1 local
set local [expr $var2 * 3]
}
proc mySecondProc { var2 } {
global myBigFatGlobalVariable
set $myBigFatGlobalVariable [expr $var2 * 3]
}
myFirstProc $myBigFatGlobalVariable 3
mySecondProc 3
在我看来, myFirstProc 会更干净并且 . 我在这里错过了什么吗?
I'm fairly new to TCL, and am providing QA on some code developed by others (no really!). There are lots and lots of global variables in this particular program, and I sometimes see upvar used, often in conjunction with global. I understand that upvar emulates pass-by-reference, but what would be the practical difference be between the two following procs?
set myBigFatGloblVariable "hello"
proc myFirstProc { var1 var2 } {
upvar 1 $var1 local
set local [expr $var2 * 3]
}
proc mySecondProc { var2 } {
global myBigFatGlobalVariable
set $myBigFatGlobalVariable [expr $var2 * 3]
}
myFirstProc $myBigFatGlobalVariable 3
mySecondProc 3
It seems to me that myFirstProc would be cleaner and . Am I missing something here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
它们相似但又略有不同。
upvar 允许您访问调用堆栈中 x 层以上的变量。
它们不一定需要是全局变量。
您可以通过传递 upvar #0 varName localVarName 使用 upvar 来模拟全局
在这种情况下,您将获得具有本地名称的全局变量。
要模拟按引用传递,您需要传递变量的名称,然后对该名称调用 upvar。
如果您知道变量的名称,则可以按原样使用它。
观察以下代码:
这返回
upvar 只是从调用堆栈获取变量的一种方法。 (调用函数)包括“全局”堆栈。
They are similar but subtly different.
upvar allows you access variables up x levels in the call stack.
They don't necessarily need to be global variables.
You can use upvar to emulate global by passing upvar #0 varName localVarName
You will get the global variable with a local name in that case.
To emulate pass by reference, you are pass the name of the variable, then call upvar on that name.
If you know the name of the variable, you can use it as is.
Observe the following code:
This returns
upvar is just a way to get at variables from the call stack. (calling functions) including the 'global' stack.
两个过程之间的最大区别是:myFirstProc 设置global“hello”,mySecondProc 设置local“hello”。
mySecondProc 引用全局 myBigFat... 来获取值“hello”,但不会更改“hello”变量的范围。
myFirstProc 接收值“hello”作为参数,然后在堆栈上一帧名为“hello”的变量与局部变量“local”之间创建链接。 设置“local”具有将“hello”设置为堆栈上一帧的效果。
查看:
如果您确实想从 mySecondProc 设置全局“hello”,则需要添加
global $myBigFatGlobalVariable
The big difference between your two procs is this: myFirstProc sets the global "hello", mySecondProc sets the local "hello".
mySecondProc references the global myBigFat... to get the value "hello", but does not alter the scope of the "hello" variable.
myFirstProc receives the value "hello" as a parameter, and then creates a link between a variable named "hello" one frame up the stack and the local variable "local". Setting "local" has the effect of setting "hello" one frame up the stack.
To see:
If you really want to set the global "hello" from mySecondProc, you'll need to add
global $myBigFatGlobalVariable
不同之处在于 upvar 1 $var local 使 local 从上一级 $var 中命名的变量中获取其值。 因此,在 myBigFatGlobalVariable 中,$var 不必在全局范围内定义。
p1 将从调用堆栈中位于其上方的第 1 层打印出 var1 的值。 全局变量总是在顶层定义,因此 upvar #0 与全局变量执行相同的操作。
The difference is that upvar 1 $var local makes local take its value from the variable named in $var from the level above. So in myBigFatGlobalVariable $var does not have to be defined at the global scope.
p1 will print out the value of var1 from the level 1 above it in the call stack. A global is always defined at the top level so upvar #0 does the same thing as global.
你是说:
我对中型到超大型 Tcl 应用程序(20k+ 行!)的经验是,使用名称空间将极大地帮助在大量全局变量中获取结构。
好的部分是,每次在代码中创建新模块时,或者通过重构一些代码,您都可以迭代地添加它们。
您可以通过 module1::counter 引用它们(就像您可以将全局变量引用为 ::counter
参见 wiki 命名空间页面 和有关命名空间的 Tcl 手册页面 有关命名空间的更多信息。
You are saying:
My experience with medium to very large Tcl applications (20k+ lines!) is that using namespaces will significantly help getting structure within the large amount of global variables.
The nice part is, is that you can add them iteratively everytime you create a new module to your code, or by refactoring some of your code.
You can refer to them via module1::counter (just as you can refer to a global variable as ::counter
See the wiki namespace page and the Tcl manual page on namespaces for more information on namespaces.