Tcl/Tk Insight: Package 模块的管理

风行水上 @ 2012-03-24 00:32:18
标签:

    模块的存在是为了更好地代码重用。

    借助auto_load和auto_index加载命令

    当要执行的命令不存时,unknown命令会被调用。

    Tcl默认的unknown命令实现会调用auto_load $cmd

    当执行命令auto_load $cmd时,Tcl解释器会在$auto_path中列出的目录中寻找并加载(source)文件tclIndex。

    tclIndex文件的内容如下,定义了加载某条命令的方法,比如:

    set auto_index(assert) [list source [file join $dir assert.tcl]]
    set auto_index(%%) [list source [file join $dir assert.tcl]]
    # ... ...
    

    tclIndex文件可以用下面的命令生成:

    auto_mkindex $dir *.tcl
    

    用package加载模块

    典型的package的用法如下:

    package require assert
    # 或者
    package require assert 1.0
    

    显然,问题的关键是如何找到要加载的文件。与auto_load类似,package命令是在$auto_path中列出的目录中寻找pkgIndex.tcl文件,其文件内容大致如下:

    package ifneeded assert 0.1 [list source [file join $dir assert.tcl]]
    

    pkgIndex.tcl文件可以用下面的命令生成:

    pkg_mkIndex -direct $dir ;# -direct 选项可以省略
    

    相应的tcl文件中需要包含package provide命令,比如

    package provide assert 0.1
    

    上面这种"-direct"的方式会在package require命令执行时加载相应的Tcl文件。还有一种-lazy模式,其对应的"pkgIndex.tcl"文件内容看起来如下:

    package ifneeded assert 0.1 [list tclPkgSetup $dir assert 0.1 \
        {{assert.tcl source {%% assert}}}]
    

    这可以通过命令pkg_mkIndex -lazy $dir来生成。

    tclPkgSetup的作用是设置$auto_index变量,将加载tcl文件的时间推迟到第一次使用包中的命令时,即所谓的lazy loading.

    用tm管理Tcl模块

    tm是Tcl8.5中开始出现的,用于辅助定位和加载Tcl模块文件。

    加载一个模块文件本质上就是source文件。tm约定了一种模块文件的命名和寻找方式。

    ::tcl::tm::path add命令可以指定一组搜寻目录(search path)。模块文件以PNAME-PVERSION.tm的形式命名。

    tm只是一种辅助工具,具体的文件加载还是要依赖于package方法。一个tm模块文件会被自动添加到package database中:

    package ifneeded PNAME PVERSION [list source MF]
    
    # MF = $tm_path/PNAME-PVERSION.tm
    

    两个(其实是一个,只是不同的写法)新的环境变量用于设置search path:

    • $::env(TCLX_y_TM_PATH)
    • $::env(TCLX.y_TM_PATH)

    tm的好处是省去了创建和管理"pkgIndex.tcl"文件的麻烦。

    标签:

      分享到:
      comments powered by Disqus

      20/23ms