Arjen Markus 2004-04-01: When using the after command to create an animated display, I often come up with a pattern like this:
proc myproc { arg1 arg2 ... } { ... do some processing ... # The animation bit if { ... another step reauired? .... } { after 1000 [list myproc $arg1 $arg2 ...] } return }
For a lazy programmer like me that is too much work:
So, I came up with this little tool ...
# schedule.tcl -- # Automatic (re)scheduling of the current procedure # # Motivation: # In some circumstances, like with animation, you get the # following pattern: # proc someproc {arguments} { # ... do whatever necessary ... # if { condition } { # # Schedule the next call # after $time [list someproc $arguments] # } # } # The problem here is that the code contains both the # name of the procedure and all of its arguments, making # changes a bit difficult. # The procedure below automates this: # proc someproc {arguments} { # ... do whatever necessary ... # if { condition } { # reschedule $time # } # } # If the delay time is not given, it defaults to 0 # Note that the reschedule procedure uses the current values # of the argument variables, so that you can use it for instance # in a countdown # proc countdown {count} { # puts $count # incr count -1 # if { $count > 0 } { # reschedule 1000 # } # } # # reschedule -- # Schedule the current (calling) procedure via the after command # Arguments: # delay Delay time in ms (defaults to 0) # Result: # None # Side effect: # The calling procedure will be called again via an after command # proc reschedule {{delay 0}} { set call_list [lindex [info level -1] 0] set argvars [info args $call_list] foreach var $argvars { lappend call_list [uplevel [list set $var]] } after $delay $call_list } # # Small test # proc print { count msg {default 0}} { puts "$count ... $msg ($default)" set msg [string range $msg 0 end-1] incr count -1 if { $count > 0 } { reschedule 100 } else { set ::forever 1 } } print 10 "and counting" vwait forever
RS uses every for such purposes, here in its full code:
proc every {ms body} {eval $body; after $ms [namespace code [info level 0]]}
AM Ah, but that fails with my countdown example as I do not use the values of the original call, but the values of the arguments when rescheduling.
Of course, your solution is more concise :)
[ [Arts and crafts of Tcl-Tk programming ]