Warm tip: This article is reproduced from serverfault.com, please click

vmd-从TCL上的另一个proc内部使用proc

(vmd - Use proc from inside another proc on TCL)

发布于 2020-12-05 21:07:22

我正在尝试在tcl中编写脚本以对VMD执行一些分析。首先,我在一个过程中创建一个atom选择,然后尝试在另一个过程中使用它。

从VMD中选择原子是作为Tcl函数实现的。从中返回的数据atomselect是要使用的函数的名称。你可以在这里阅读更多内容

当我在外部创建原子选择时,proc可以在内将其用作global但是,既然我正在其中一个中创建它,那么当我尝试使用它时,它只是一个带有过程名称的字符串。

恢复,

这有效:

set all [atomselect top all]

proc test {} {
    global all
    $all num
}

test # Outuputs 7111

但这不是:

proc create {} {
    global all
    set all [atomselect top all]
}

proc test {} {
    global all
    $all num
}

create
test # Outputs -> invalid command name "atomselect1"
Questioner
Arthur Pereira
Viewed
0
Donal Fellows 2020-12-06 06:32:38

问题在于,atomselect该过程返回时,将删除该命令创建的命令。强烈怀疑这是通过使用局部变量删除跟踪(在某些未使用的变量上)完成的。atomselect在全球范围内运行时,有没有这样的天然缺失事件(除非全局命名空间被删除,这是一个解释,结束事件),因此走线不会被调用和所创建的命令无限期地持续存在。

如果我们这样重写你的创建:

proc create {} {
    global all
    # Double quotes just because of the highlighting here
    set all [uplevel "#0" atomselect top all]
}

然后atomselect在全局范围内运行(并且创建的命令应保留),但是其余所有代码都在过程中。

更正确地,应该这样进行:

proc create {} {
    global all
    # Double quotes just because of the highlighting here
    set all [uplevel "#0" [list atomselect top all]]
    # Or this, to better show that we're talking about running a command:
    #   set all [uplevel "#0" [list \
    #       atomselect top all]]
}

当你传递带有空格(或其他元语法字符)的参数时,这一点变得更加重要,因为list这不仅会产生列表,而且还会产生无替换的命令。(实际上,构建命令和命令片段绝对是该list命令的主要用途之一;用于普通数据存储和操作的实际列表往往是由其他一些命令创建的。)