我有一组proc和命名空间,如下所示:
namespace eval ::_API {
if {[info exists ::_API::API_ids]} {
catch {API erase -ids [array names ::_API::API_ids]}
}
catch {unset API_ids}
array set API_ids ""
}
proc ::_API::erase { } {
foreach id [array names ::_API::API_ids] {
if {::_API::API_ids($id) == 0} {
continue
}
if {[catch {API -id $id -redraw 0}] != 0} {
set ::_API::API_ids($id) 0
}
}
Redraw ;# I'm not concerned about this part
# and I'm fairly certain it can be ignored
}
proc erase { } {
::_API ::erase
}
::_API::API_ids
是一个包含点的数组(例如0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
)。脚本的作用是擦除表中的点。
我想将命名空间::_API
转换为proc,以便我可以使用GUI按钮来调用proc。它目前直接在一些其他脚本(映射表中的点)之后,我想只在需要时擦除它们;即按下按钮时。
我已经尝试直接运行::_API::erase
,但它无效:
proc ::_API::erase { } {
foreach id [array names ::_API::API_ids] {
if {::_API::API_ids($id) == 0} {
continue
}
if {[catch {API -id $id -redraw 0}] != 0} {
set ::_API::API_ids($id) 0
}
}
Redraw
}
我认为关于命名空间可能会遗漏一些东西。我试过阅读documentation,但我不太明白它们是如何工作的。
答案 0 :(得分:2)
您真正必须做的第一件事是使用variable
来声明变量。由于一些相当丑陋的原因,未能做到这一点会导致可变分辨率的“乐趣”使事情以你不期望的方式发生:
namespace eval ::_API {
variable API_ids; ##### <<<<<<< THIS <<<<<<< #####
if {[info exists ::_API::API_ids]} {
catch {API erase -ids [array names ::_API::API_ids]}
}
catch {unset API_ids}
array set API_ids ""
}
其次,你可能应该考虑使用真正的OO而不是试图伪造它。例如,使用TclOO,您将编写如下内容:
oo::class create APIClass {
variable ids
constructor {} {
array set ids {}
}
method erase {} {
foreach id [array names ids] {
if {$ids($id) == 0} continue
if {[catch {
API -id $id -redraw 0
}]} {
set ids($id) 0
}
}
Redraw
}
# Allow something to reference the ids variable from the outside world
method reference {} {
return [my varname ids]
}
}
APIClass create _API
# [_API erase] will call the erase method on the _API object
这简化了一些事情,实际上你可以考虑将绘图和数据管理耦合得比我上面的更接近;它只是表明你能做什么。 (我发现当我使用对象时它会使事情变得更简单,因为它们比普通命名空间对它们有更强的生命周期感。)
答案 1 :(得分:1)
您的意思是您希望将命名空间初始化代码转换为过程。以下示例应该实现。
namespace eval ::_API {
}
proc ::_API::initialize {} {
variable API_ids
if {[info exists API_ids]} {
catch {API erase -ids [array names API_ids]}
unset API_ids
}
array set API_ids ""
}
... more definitions ...
::_API::initialize
我们首先声明命名空间。然后在过程中复制原始代码。由于没有必要设置不存在的变量,我们将unset移动到仅在变量存在时才运行的块。 在命名空间定义的末尾,通过调用其初始化函数来初始化命名空间。