我在TCL中看到了一些这样的代码:
namespace eval ::info {
set count 0;
set id 1;
set role admin;
namespace export *
}
proc ::info::setcount {
set ::info::count 0;
}
proc ::info::setId {
set ::info::id 1;
}
proc ::info::setRole {
set ::info::role user;
}
命名空间 ::info 中定义了三个变量,但是三个 procs(setcount setId setRole( 没有在命名空间中声明,似乎它们是在 ::info 之外定义的,这是允许的吗? 这是如何工作的?
这些过程在 ::info
命名空间中定义。它们只是不在namespace eval
范围内,该命令仅在必要时创建命名空间,然后在该上下文中执行给定的脚本。在命名空间的上下文中执行会更改proc
放置这些命令时创建的命令的方式,当这些命令的名称不是完全限定的时。命名空间独立于namespace eval
调用而存在。不过,变量必须在命名空间中声明;这避免了解决变量时遇到的一些非常讨厌的麻烦,这些变量可能会让人们感到困惑。
就个人而言,我更喜欢这样编写代码:
namespace eval ::foo {
proc bar ... {
...
}
}
但我知道其他人不同意我的观点。写下你喜欢的东西,因为 Tcl 适用于任何一种方案。
namespace eval
命令
- 创建命名空间(如果不存在(
- 从该命名空间中运行提供给它的代码
从命名空间中定义的过程(这是所有过程,因为默认命名空间是 ::)
- 如果前面有绝对命名空间,则将在指定的命名空间中定义该命令
- 如果前面是相对命名空间,则将相对于当前命名空间定义该命令
因此
namespace eval bob {
namespace eval joe {
proc proc1 {} {}
}
proc proc2 {} {}
proc ::proc3 {} {}
proc joe::proc4 {} {}
}
proc proc5 {} {}
proc bob::joe::proc6 {} {}
proc ::bob::joe::proc7 {} {}
将存在以下命令
::bob::joe::proc1
::bob::proc2
::proc3
::bob::joe::proc4
::proc5
::bob::joe::proc6
::bob::joe::proc7
请注意,从全局命名空间调用全局命名空间中的命令时,前面可以带有::
,也可以不前面。任何命名空间中的命令也是如此。
namespace eval bob {
proc2 ;# calls ::bob::proc2
::proc5 ;# calls ::proc5 (proc5 in the global namespace)
joe::proc4 ;# calls ::bob::joe::proc4
}
值得注意的是,原始命令名称(根本没有命名空间限定符(将查找当前命名空间,然后,如果在那里找不到命令,则查找全局命名空间。
namespace eval bob {
proc5 ;# calls ::proc5 since there is no ::bob::proc5
}