使用after评估延迟命令中的变量

时间:2018-10-25 18:59:02

标签: tcl

我已经定义了变量的过程,然后按照该步骤延迟使用变量。

问题在于延迟命令在执行命令时而不是在给出命令时处理变量。考虑以下示例:

该代码尚未经过测试,但无论如何要点很明确:

for {set i 0} {$i < 100} {incr i} {
    set outputItem $i
    set time [expr 1000+100*$i]
    after $time {puts "Output was $outputItem"}
}

我希望打印以下内容:

Output was 1
Output was 2
Output was 3
...

但实际上它会打印:

Output was 100
Output was 100
Output was 100

我猜这表明,在启动after命令后,tcl会保留参数名称(而不是变量的值)。

有什么方法可以将变量名替换为变量内容,以便延迟命令(在xxx yyy之后)可以按需工作?

1 个答案:

答案 0 :(得分:1)

问题是这一行:

after $time {puts "Output was $outputItem"}

$outputItem的替换发生在after事件触发时,而不是在您定义它时。 (大括号可以防止其他任何事情。)要获得所需的内容,您需要列表引用,这是通过list命令完成的:

after $time [list puts "Output was $outputItem"]

list命令生成列表和预替换命令(由于Tcl语法的定义方式)。 很棒用于构建您以后将要调用的东西。我想它也可能被称为make-me-a-callback,但是后来人们会想知道它在创建列表中的用途。两者都做。

如果您的回调需要两个或多个命令,请使用帮助程序(或apply)将其包装为一个命令;尽力减少使回调与多个直接命令一起使用的困惑是完全值得的。