2

这是我正在测试的代码:

proc check_eval {} {
    set cmd {set return_val {}; set return_val}
    puts "Command to evaluate : $cmd"
    uplevel eval $cmd
}

我遇到了以下问题:当我调用“check_eval”时,看起来语句“set return_val {}”被忽略了。即,interpeter 在调用范围内寻找现有的 return_val 变量。例子:

tcl>unset return_val
tcl>check_eval
Command to evaluate : set return_val {}; set return_val
can't read "return_val": no such variable
while evaluating check_eval


tcl>set return_val 556
556
tcl>check_eval
Command to evaluate : set return_val {}; set return_val
556
tcl>

另一方面,如果我将程序中的“set return_val {}”替换为“set return_val 10000”,运行时将显示 10000:

tcl>set return_val 556
556
tcl>check_eval
Command to evaluate : set return_val 10000; set return_val
10000
tcl>set return_val
10000

有人可以解释一下这里发生了什么吗?

谢谢。

4

1 回答 1

4

您正在执行两个级别的评估/解释,首先使用uplevel然后使用eval,并且围绕 cmd 脚本的大括号分组仅保护您免受第一个级别的影响。

你不需要eval,这就足够了:

uplevel $cmd

编辑evaluplevel concat:enate 将它们的所有参数一起放入一个平面字符串并将其作为脚本进行评估(uplevel您可以选择另一个堆栈框架来运行它)。他们不使用第一个参数作为单个命令名称,其余参数作为参数发送到该命令。如果是这种情况,您会收到一条错误消息,eval指出找不到命令“set return_val {}; set return_val”。所以你使用eval正确但uplevel错误。

uplevel运行这个脚本...

eval set return_val {}; set return_val

...它的破坏方式不止一种,因为您没有列出引号(组)它的论点。

eval在您的示例中不需要,但是如果您需要调用单个命令上层,而没有连接它的参数,当您不需要任何替换时引用静态字符串的方法是使用大括号:

uplevel {after 1000 {set return_val {}; set return_val}}

...以及引用具有替换值的动态字符串的方法是list

set cmd {set return_val {}; set return_val}
uplevel [list after 1000 $cmd]
于 2013-04-15T12:06:40.710 回答