我刚开始使用TCL并试图了解如何最好地定义和集成模块。在包+命名空间概念中似乎付出了很多努力,但从我可以看出,interp对于每个可想象的场景都更强大和更精益。特别是当涉及到隐藏和重命名程序时,还缺少全局命名空间中的蠕变。使用package +名称空间的唯一原因似乎是因为“曾几何时Sun就这么说”。
我什么时候应该使用package + namespace而不是interp?
答案 0 :(得分:3)
命名空间和包一起工作。口译员是其他的东西。
名称空间是Tcl中的小规模命名上下文。它可以包含命令,变量和其他名称空间。您可以通过本地名称(foo
)或通过限定名称(bar::foo
)引用命名空间中的实体;如果限定名称以::
开头,则它相对于(interpreter-)全局名称空间,并且可用于从解释器中的任何位置引用其命令或变量。 (FWIW,TclOO对象系统在命名空间之上进行了广泛的构建;每个对象都有一个命名空间。)
包是某种类型库提供的一堆代码的高级概念。包具有抽象名称(名称 not 必须与库的实现存储在磁盘上的方式相对应)和不同的版本;如果有必要,你可以要求特定的版本,但大多数时候你不打扰。包可以通过多种机制实现,但它们几乎都归结为source
一些Tcl脚本和load
一些DLL。几乎所有的包都声明了命令,并且通常鼓励它们将这些命令放在名称空间中,并使用与包相同的通用名称。但是,由于各种原因,相当多的旧软件包不会这样做,主要是为了与现有代码兼容。
解释器是Tcl中的安全上下文。默认情况下,Tcl创建一个解释器(如果它在wish
中设置控制台窗口,则创建另一个解释器)。一个解释器中的命名实体与另一个解释器中的命名实体完全不同,但有一些关键的例外:
频道在所有口译员中都有通用名称。这意味着口译员可以谈论另一个口译员拥有的频道,但只是能够提及其名称并不允许访问该频道。 (默认情况下共享stdin
,stdout
和stderr
个频道。)
interp alias
命令可用于创建别名命令,这样在一个解释器中调用命令(别名)可以导致调用另一个解释器中的命令(实现),所有参数都安全地通过了。这允许一个解释器公开它希望另一个解释器访问的任何特殊调用而不会失去控制,但是这些命令的实现可以安全地对这些参数采取行动。
安全解释器是指默认情况下Tcl的不安全命令。 (例如open
,socket
,source
,load
,cd
等等。)创建安全子解释器的父解释器可以使用别名机制,准确添加所需的功能;它非常类似于OS系统调用,除非您可以轻松地创建自己的特定应用程序。
Tcl的线程包旨在为每个线程创建一个解释器(并且别名机制不能跨线程工作)。这意味着默认情况下共享资源的方式很少,并且线程间通信是通过排队的消息传递完成的。
通常,每个解释器最多需要一次打包,并且建议您如何访问大多数第三方功能。命名空间相当轻量级,用于各种各样的事情,口译员被认为是昂贵的;许多完全生产级别的Tcl脚本只能与一个解释器一起工作。 (线程甚至比解释器更昂贵;最好将您创建的线程数与您希望强加的硬件负载相匹配,可能是通过使用合适的线程池。)
答案 1 :(得分:1)
模块的目的是提供模块化代码,即模块编写者的知识和控制之外的应用程序可以轻松使用的代码,并封装自己的内部。
基于包命名空间和解释器的模块可能同样擅长封装,但是使基于解释器的模块在任意应用程序中运行良好并不容易(当然可能)。
我自己的观点是,解释器是应用程序级别(我主要将它们用于用户输入和控制评估),而不是模块级别。命名空间和包都有它们的瑕疵,但在大多数情况下,它们会以最小的麻烦做到对它们的期望。
我的建议是,如果您为自己的利益编写模块,并且口译员为您提供服务,请务必使用它们。如果您编写其他人要使用的模块,可能包括18个月内的自己,那么您应该坚持使用命名空间和包。