我正在尝试理解在用c编写的TCL扩展中使用命名空间的正确方法。
我研究了其他人的一些扩展,我看到了不同的变化。
- 有些创建了一个命名空间::tcl::mypackage
- 有的只创建命名空间::mypackage
显然,在tcl程序函数中,第一个版本是用::tcl::mypackage::foo调用的。在第二个版本中,它们被调用为::mypackage::foo.
与我所期望的相反,::tcl::mypackage是而不是与::mypackage 相同此外,tcl命令listns显示两种类型的名称空间,如::pkg和::tcl::encoding。更令人困惑的是,一些命名空间以两种方式列出:::tcl::zlib和::zlib.
那么在命名空间前面加::tcl有什么意义呢?或者换句话说,是什么::tcl命名空间?
Tcl命名空间名称是递归的;您可以将名称空间放在其他名称空间中。只有全局名称空间(其名称为空,但通常称为::
,单个名称空间分隔符)在基本语言语义中实际上是特殊的。
::tcl
包(及其子包)是Tcl自己放置实现的空间。它通常不应该被用户代码改变(有一个例外),因为它的内容不被认为是API的一部分,除非有明确的文档说明。(因此::tcl::prefix
是API的一部分;它有一个手册页,我们保证它会在那里。)如果我们从头开始重新编写Tcl—我们不会做这样的事情!-那么所有的Tcl标准命令都将放在那里(但它将在默认的名称解析路径上)。
如果不是因为遗留(大量)现有代码,全局命名空间将被认为是应用程序代码的唯一域。
此规则的例外是tcl::mathfunc
名称空间,它旨在供用户编辑。在这里放一个命令使它成为一个可以从表达式调用的函数;函数实际上是通过进行简单的名称转换来获得命令名称并调用来处理的。
::tcl
的大多数子命名空间完全没有文档记录。::tcl::mathop
则不是,它将表达式操作符作为命令包含。这使您可以执行诸如对整个数字列表求和或链式比较之类的操作。你可能不应该在里面编辑任何东西;更改这些命令不会改变表达式操作符本身(它们是生成字节码操作的另一种方式),但可能会破坏代码。
::tcl
内部的另一个要注意的命名空间是tcl::unsupported
;里面有一些东西可以做一些有趣的事情(比如字节码操作和值类型检查),但我们没有提供API保证。在字节码操作的情况下,这是因为我们强烈保留更改使用的字节码的权利,而在类型检查的情况下,这是因为Tcl的可观察语义不应该依赖于值的当前缓存类型(而是取决于值是否可以转换为类型)。但是它们是有用的调试工具,可以让你弄清楚为什么代码出乎意料地慢。
最后,::oo
和::tk
名称空间应该以同样的方式处理。