以下是我正在测试的代码:
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
有人能解释一下这里发生了什么吗?
感谢。
答案 0 :(得分:4)
您正在进行两个级别的评估/解释,首先使用uplevel
然后使用eval
,并且cmd脚本周围的大括号分组仅保护您免受第一个的影响。
您不需要eval
,这就足够了:
uplevel $cmd
编辑:eval
和uplevel
concat
:将所有参数一起添加到一个扁平字符串中并将其作为脚本评估(使用uplevel
,您可以选择另一个堆栈帧来运行它)。它们不将第一个参数用作单个命令名称,将其余参数用作发送到该命令的参数。如果是这种情况,您将从eval
收到一条错误消息,指出无法找到命令“set return_val {}; set return_val”。因此,您正确使用eval
但uplevel
错误。
uplevel
运行此脚本......
eval set return_val {}; set return_val
...它的方式多于一个,因为你没有列出引用(组)的论据。
在你的例子中不需要 eval
,但是你需要调用单个命令uplevel,而不需要连接它的参数,当你不需要任何替换时引用静态字符串的方法,是括号:
uplevel {after 1000 {set return_val {}; set return_val}}
...以及使用替换值引用动态字符串的方法是使用list
:
set cmd {set return_val {}; set return_val}
uplevel [list after 1000 $cmd]