0

我想将一个模块加载到一个模块文件中(以解决依赖关系)。

我的模块:

#%Module########################################
##
##  Modulefile
#
proc ModulesHelp { } {
    puts stderr "Env for MyProg"
}
proc addPath {var val} {
    prepend-path $var $val
}
module load MyOtherModule 
addPath   PATH   /opt/MyModule/bin

我的其他模块:

#%Module########################################
##
##  Modulefile
#
proc ModulesHelp { } {
    puts stderr "Env for MyOtherProg"
}
proc addPath {var val} {
    prepend-path $var $val
}
addPath   PATH   /opt/MyOtherModule/bin

当我运行时module load MyModule,两个模块似乎都已加载,但环境不正确:

$module list
Currently Loaded Modulefiles:
  1) MyModule   2) MyOtherModule
$echo $PATH
/opt/MyModule/bin:/usr/bin:/bin

如果我添加该行foreach p [array names env] { set tmp $env($p) }或至少set tmp $env(PATH)在该module load MyOtherModule行之后的 MyModule 中,则正确修改了环境。如果我不使用我的函数addPath但我prepend-path直接使用命令,它也可以正常工作,这有点烦人,因为我当然想在addPath函数中做更多的事情。

任何人都知道发生了什么以及我错过了什么?

4

1 回答 1

3

prepend-path可能是在做一些“聪明”的事情来管理变量;它到底是什么我不知道也不需要知道,因为我们可以使用通用 Tcl 解决所有问题。为了使您的包装工作,请使用uplevel在适当的范围内评估代码,尽管您需要考虑是使用全局范围(名称#0)还是调用者的范围(1,这是默认值);addPath当从全局级别调用您的过程时,它们是相同的,但在其他方面可能会完全不同,而且我不知道模块系统处理还会发生什么其他奇怪的事情。

为了演示,试试这个addPath

proc addPath {var val} {
    puts stderr "BEFORE..."
    uplevel 1 [list prepend-path $var $val]
    puts stderr "AFTER..."
}

我们使用list构建在调用者范围内评估的事物,因为它保证生成无替换的单命令脚本。(还有有效的列表。)这是在 Tcl 中进行代码生成的全部秘诀:保持简单,用于list执行任何所需的引用,当事情变得复杂时调用帮助程序(带有合适的参数),并用于uplevel控制评估范围.

(注意:upvar它也很有用——它将局部变量绑定到另一个范围内的变量——但这不是你在这里推荐使用的。我提到它是因为如果你做任何更复杂的事情它可能会很有用......)

于 2014-05-21T21:06:19.830 回答