Reputation: 47
I have process were variables are defined, and following that procedure the variables should be used after a delay.
The problem is that the delayed command process the variables when the command is executed instead of when the command is given. Consider the following example:
The code is not tested, but the point should be clear anyway:
for {set i 0} {$i < 100} {incr i} {
set outputItem $i
set time [expr 1000+100*$i]
after $time {puts "Output was $outputItem"}
}
Which I would hope print something like:
Output was 1
Output was 2
Output was 3
...
But actually it prints:
Output was 100
Output was 100
Output was 100
Which I guess shows that tcl keeps the parameter name (and not the value of the variable) when the after command is initiated.
Is there any way to substitute the variable name to the variable content, so that the delayed command (after xxx yyy) works as desired?
Upvotes: 0
Views: 162
Reputation: 137567
The problem is this line:
after $time {puts "Output was $outputItem"}
The substitution of $outputItem
is happening when the after event fires, not at the time you defined it. (The braces prevent anything else.) To get what you want, you need list quoting, and that's done with the list
command:
after $time [list puts "Output was $outputItem"]
The list
command builds lists… and pre-substituted commands (because of the way Tcl's syntax is defined). It's great for building things that you're going to call later. I guess it could have been called make-me-a-callback
too, but then people would have wondered about its use for creating lists. It does both.
If your callback needs to be two or more commands, use a helper procedure (or an apply
) to wrap it up into a single command; the reduction in confusion at trying to make callbacks work with multiple direct commands is totally worth it.
Upvotes: 1