tcl 命名空间之我见

http://hi.baidu.com/jiajiazc/blog/item/24f5cbb57a24e2c337d3cacf.html

 tcl的发展紧随着软件发展的过程,类似c逐渐变成了c++ 然后是csharp,计算机语言都在发展。
tcl最初也是面向过程的,后来出现了包,当不同的人进行同一项目的开发时,很容易出现,变量和函数名的冲突,即 张三用了某些变量或者proc,李四也选用了同样的名字。
这样的后果就是 当把两个人的程序合到一起时,程序的行为变的不可控,类似的情况还有包,就是A包里面的东东很可能跟B包变量proc重复,这样最后被加载的包中信息会覆盖前面的。这也不是我们想要看到的。
因此tcl引入了命名空间 namespace 的概念。这个概念在java c++都有。不再多赘述
当我们想使用命名空间是,首先确定下命名空间的名字,最好跟包名字一直,名字最好是字母数字组成,不要使用空格或者冒号的,以免引起误解。
在命名空间中定义的变量,需要使用variable声明,在命名空间内部使用set设定的变量,认为是该命名空间内部的。如果在命名空间内部取某个该命名空间没有的变量,解释器会给该变量前面加上两个冒号再取值,也即取根命名空间下的变量,也即全局变量。
set v1 value0;
set v4 value4;
namespace eval ::ns {
variable v1 value1 v2 value2;
set v3 value3;#解释器会设定v3也是variable的
puts $v4;#解释器会按照::v4来取值
}
puts $v1;#返回value0
puts $::ns::v1;#返回 value1
上面说了变量 再说 proc
可以在eval体内定义变量也可在在它外面定义

namespace eval ::ns {
proc p1 {} {
puts [namespace current]::p1;#namespace current返回当前命名空间
}
}
proc ::ns::p2 {} {
puts [namespace current]::p2
}
在命名空间内部可以直接调用 p1 p2 在其他地方需要使用::ns::p1或者 ns::p1
嵌套的命名空间
namespace eval ::ns1 {
variable vns1 valuens1
proc p1 {} {puts [namespace current]::p1}
namespace eval ns2 {
variable vns2 valuens2
proc p2 {} {puts [namespace current]::p2}
namespace eval ns3 {
variable vns3 valuens3
#puts $vns2;#此处如果想调用 ns2中的变量 需要使用ns1::ns2::vns2
puts $ns1::ns2::vns2
proc p3 {} {puts [namespace current]::p3}
}
}
}
如上 嵌套的命名空间,我们可以调用其中的变量 或者 proc
% ns1::p1
::ns1::p1
% ns1::ns2::p2
::ns1::ns2::p2
% ns1::ns2::ns3::p3
::ns1::ns2::ns3::p3
如果在某个命名空间中想调用其他命名空间的变量,需要使用全路径 即一堆的::,这样做可能很烦
如果跟下面一样命名空间的名字很长 或者 层次很深,我们想调用其中的proc就必须写一大堆代表路径的东西。
namespace path 可以定义查找变量的路径(tcl 8.5新增)
namespace eval ::ns123453454354353 {
proc p1 {} {puts ppppp1}
}
namespace path ::ns123453454354353
p1
ppppp1
也可以引入某个命名空间中的proc,但此时 在被引入的命名空间必须export 该proc
namespace eval ::ns123453454354353 {
proc p1 {} {puts ppppp1}
namespace export p1
}
namespace import ::ns123453454354353::*;#*代表引入所有export的proc,也可以是需要引入的proc
如果引入后,又想删除,可以用namespace forget 命令进行删除
namespace forget ?pattern pattern ...?
另外tcl还提供了 查询当前命名空间的子空间以及父空间的功能
namespace children nameofnamespace
namespace parent nameofnamespace
如果想判断某个命名空间是否存在可以使用
namespace exists nameofnamespace
为了不至于引起错乱,对于可能出现的无法预知的proc可以使用
namepsace unkonwn 预先处理
如果想删除某个命名空间中的变量 proc可以使用下面命令
namespace delete nameofnamespace
为了给namespace中的变量或proc写回调函数,需要使用namespace code命令
namespace code script
namespace eval ::ns123453454354353 {
proc p1 {} {puts ppppp1}
proc traceenter {args} {puts $args}
trace add execution p1 enter [namespace code traceenter];
}
如果想在某个命名空间中运行一个脚本可以使用namespace inscope命令
namespace inscope namespace script ?arg ...?
namespace eval ::ns123453454354353 {
}
namespace inscope ns123453454354353  {puts [namespace current]}
返回::ns123453454354353
如果引入了某个namespace,这是需要得到某个proc的全路径,即带命名空间的proc全路径,使用namespace origin command 命令
% namespace origin p1
::ns123453454354353::p1

namespace ensemble subcommand ?arg ...?
namespace qualifiers string
namespace tail string
namespace upvar namespace otherVar myVar ?otherVar myVar ...
namespace which ?-command? ?-variable? name

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值