tcl - 在 TCL 上的另一个 proc 内部使用 proc
问题描述
我正在尝试在 tcl 中编写一个脚本来对 VMD 执行一些分析。首先我在一个过程中创建一个原子选择,然后我试图在另一个过程中使用它。
来自 VMD 的原子选择被实现为 Tcl 函数。返回的数据atomselect
是要使用的函数的名称。你可以在这里阅读更多。
当我在 a 之外创建原子选择时,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"
解决方案
问题是该命令创建的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
;普通数据存储和操作的实际列表往往由其他命令组成。)
推荐阅读
- xml - XSLT - 将相似节点组合在一起并删除重复节点
- android - 如何使用 volley 在 android 的幻灯片 viewPager 中获取图像
- ruby-on-rails - 如何在 Rails 中添加与现有对象的关系
- ios - 为什么 NSDecimalNumber.notANumber.intValue 返回 9?
- reactjs - 使用 React Navigation 在 React Native 应用程序之间共享状态
- google-analytics - 跨子域跟踪引荐
- java - gson.toJson 声明了多个名为 XX 的 JSON 字段
- ruby - 更好的三元条件
- excel - 将国家分组到正确的大陆并在数据透视图中为所有大陆设置过滤器
- javascript - 更好的编码方式,而不是使用带有 `insertAdjacentHTML` 的全新代码