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:- Repeat the name of the procedure
- Construct a list for the after command with the right arguments (a repetition of the proc's header)
- What if I need another list of arguments or change the namespace?
# 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 foreverRS uses every for such purposes, here in its full code:
proc every {ms body} {eval $body; after $ms [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 ]]

