TCL命名空间和堆栈帧有什么区别?
Upvar创建指向different stack frame中变量的链接,有时称为call stack或different scope。TCL命名空间和堆栈帧有什么区别?
Upvar还用于为全局(或名称空间)变量2创建别名。但是命名空间仅由namespace eval命令创建。一个新的堆栈框架由proc命令创建。
命名空间和调用堆栈似乎是TCL naming context可以更改的两种方式。 Upvar和Uplevel可以在名称空间和调用堆栈上工作。
我说得对吗?我还没有看到调用堆栈和命名空间之间的直接比较,因此我的问题。
不,不是。命名空间和调用框架是非常不同的概念。命名空间是可以消除同义词歧义的名称的层次结构。程序中可能有三个名为foo
的变量,但如果将它们放在不同的名称空间中,它们不会发生冲突。命名空间可以用于变量名和命令名。一旦使用namespace eval
创建,名称空间的内容将始终可用,直到您致电namespace delete
。
调用堆栈是一系列堆栈帧。第一个堆栈帧#0始终存在。无论何时调用命令,都会创建其他堆栈框架(这主要适用于用户定义过程的命令,“内置”命令遵循其自己的规则)。命令返回时,它们会再次被销毁。所以,如果你命令A和A调用命令B和B调用命令C,你有一个调用堆栈看起来像这样:
#3 : <C's variables>
#2 : <B's variables>
#1 : <A's variables>
#0 : <global and namespace variables>
每个堆栈帧是在意义上的范围,只有变量在那里创建或导入到它可以访问,除非你使用upvar
。其他一切都是隐藏的。在大多数编程语言中,可以从内部作用域自动访问外部作用域的名称,例如全局作用域。在Tcl中不是这样。
使用upvar
您可以让命令查看自己堆栈框外的事情。 C可以使用upvar #0 foo bar
为全局变量foo
创建别名(bar
),或者使用upvar 1 baz qux
(不带#的注释)为B的堆栈帧中的变量baz
创建别名(qux
)。
uplevel
命令可以沿着相同的行使用在另一个栈帧中执行脚本,包括全局脚本。在执行期间,脚本可以访问堆栈帧中的所有内容,但没有其他内容,包括从中调用的堆栈帧中的变量。
C也可以使用upvar #0 ::abc::def ghi
为名称空间变量::abc::def
创建别名,但不要这样做,请改用namespace upvar ::abc def ghi
。
而不是upvar #0 foo foo
你可以使用global foo
导入一个全局变量。在名称空间中定义的命令内,variable
命令可以导入在同一名称空间中定义的变量。
将#upvar
或uplevel
分为#0(全局帧)或1(呼叫者的帧)通常是有用的。使用其他帧编号很容易出错,通常表示设计不佳。调用upvar 0 foo bar
在同一个堆栈帧中为变量(foo
)创建一个别名(bar
),这可能会非常有用。
由正在处理的事件调用的命令在调用堆栈外部使用全局级别执行。他们无法到达活动的堆栈帧并访问驻留在其中的变量。
一个简单的示范:
namespace eval ::abc {
variable def 42
proc xyz {} {
variable def
}
}
set foo 1138
proc A {} {
B
}
proc B {} {
set baz 1337
C
}
proc C {} {
upvar #0 foo bar
puts $bar
upvar 1 baz qux
puts $qux
namespace upvar ::abc def ghi
puts $ghi
}
只有一些命令推堆栈帧。每个人都知道的是程序调用和'命名空间评估'。 (还有其他几个,特别是TclOO ...) – 2015-01-15 19:43:06
谢谢,@Hoodiecrow,你填写了一些细节。很多使用Google的人向我透露,名称空间与调用框架不同。而且这些命名空间是可选的,也许最好在小脚本中避免(但对代码重用有用)。调用过程被调用时也会创建调用框架。进一步澄清:在我的问题中,我是否说过任何不真实的东西? – 2015-01-16 00:10:42
@ user901750:有一些有问题的陈述。你在说栈架有时被称为调用堆栈。这是错误的,但我认为这是一个错误? 'proc'命令不会创建栈帧(但它创建的命令在被调用时会执行)。命名空间不会改变Tcl的命名上下文,但是'namespace eval'会(通过创建一个新的堆栈帧)。 'upvar'和'uplevel'不能用于(操作)名称空间,但可以像处理变量的其他任何命令一样访问名称空间变量。 – 2015-01-16 08:50:56