0

モジュールを modulefile にロードしたいと思います (依存関係を解決するため)。

マイモジュール:

#%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

MyOtherModule:

#%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)の後に MyModuleを追加するmodule load MyOtherModuleと、環境が正しく変更されます。関数を使用しない場合でも問題なく動作します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 に答える