Env не изменяется при загрузке модуля в файл модуля

Я хотел бы загрузить модуль в файл модуля (для разрешения зависимостей).

MyModule:

#%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 Функция конечно.

Кто-нибудь как идея о том, что происходит и что мне не хватает?

1 ответ

Решение

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 контролировать объем оценки.

(NB: upvar также может быть полезен - он связывает локальные переменные с переменными в другой области видимости - но это не то, что вам рекомендуется использовать здесь. Я упоминаю об этом, потому что это может быть полезно, если вы делаете что-то более сложное…)

Другие вопросы по тегам