gpt4 book ai didi

namespaces - TCL 命名空间和栈帧有什么区别?

转载 作者:行者123 更新时间:2023-12-02 06:57:42 29 4
gpt4 key购买 nike

Upvar 在 different stack frame 中创建一个变量链接,有时称为 call stack , 或 different scope .

Upvar 还用于为全局(或 namespace )变量创建别名 2 .但是 namespace 仅由 namespace eval 创建命令。 proc 命令创建了一个新的堆栈帧。

命名空间和调用堆栈似乎是 TCL naming context 的两种方式可以换。 Upvar 和 Uplevel 可以在命名空间和调用堆栈上工作。

我做对了吗?我还没有看到调用堆栈和命名空间之间的直接比较,因此我的问题。

最佳答案

不,不完全是。命名空间和调用框架是非常不同的概念。 namespace 是可以消除同义词歧义的名称的层次结构。您的程序中可能有三个名为 foo 的变量,但如果将它们放在不同的 namespace 中,它们就不会发生冲突。命名空间可用于变量名和命令名。一旦使用 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 命令可以沿同一行使用,以在另一个堆栈框架(包括全局堆栈框架)中执行脚本。在执行期间,脚本可以访问该堆栈帧中的所有内容,但不能访问其他内容,包括从中调用 uplevel 的堆栈帧中的变量。

C 还可以使用 upvar #0::abc::def ghi 为命名空间变量 ::abc::def 创建别名,但不要这样做那,请改用 namespace upvar::abc def ghi

您可以使用 global foo 来导入全局变量,而不是 upvar #0 foo foo。在命名空间中定义的命令中,variable 命令可以导入在同一命名空间中定义的变量。

upvaruplevel 放入#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
}

关于namespaces - TCL 命名空间和栈帧有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27970369/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com