Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Function calling itself with after

136 views
Skip to first unread message

Stuart

unread,
Jun 11, 2012, 11:59:31 PM6/11/12
to
I was just wondering if there are any drawbacks to doing something like this:

proc Repeat {} {

{
execute some Tcl/Tk code
}

# Repeat after 30minutes have elapsed'

after 18000000 Repeat
}

Thanks in advance..

Stuart

George Petasis

unread,
Jun 12, 2012, 2:42:31 AM6/12/12
to Stuart
No, there is not. This is something very common.

George

arjenmarkus

unread,
Jun 12, 2012, 3:05:42 AM6/12/12
to
Actually, this has been canonicalized as the [every] procedure:
http://wiki.tcl.tk/9299.

It allows you to simply do:

every 18000000 repeat

Or:

set user "Stuart"
every 18000000 [list puts "Hello, $user"]

(leave it to the Wiki and its contributors to explore all manner of
variations on the theme ;))

The thing to note is that any code run via an [after] command runs in
the global namespace - it is independent of any procedure that called
the [after] command. Therefore you do not have access at the time the
scheduled command runs to local variables. It also means that there
are no problems with running it millions of times - there is no stack
that grows and grows as you would have with a recursive call.

Regards,

Arjen

Ralf Fassel

unread,
Jun 12, 2012, 3:41:06 AM6/12/12
to
* Stuart <bigd...@aol.com>
| I was just wondering if there are any drawbacks to doing something like this:
| proc Repeat {} {
| {
| execute some Tcl/Tk code
| }
| # Repeat after 30minutes have elapsed'
| after 18000000 Repeat
| }

Possibly two problems:
- if Repeat is called twice during the 30 minutes, it will also schedule
*two* reinvocations.
- in case of an error in the Tcl/Tk code the new 'after' invocation is
not triggered, so the repetition stops.

If it is crucial that the repetition never stops, either 'catch' the
Tcl/Tk code, or invoke 'after' as first thing in the proc, probably
together with a global id to prevent multiple reinvocations:
set ::repeat_id {}
proc Repeat {} {
after cancel $::repeat_id
# Repeat after 30minutes have elapsed
set ::repeat_id [after 18000000 Repeat]
# some Tcl/Tk code ...
}

R'

Uwe Klein

unread,
Jun 12, 2012, 3:40:17 AM6/12/12
to
There is some ambivalence in that construct.

proc do_mystuff {} {
# tclcode
}
set ::delay 19000
proc repeat {} {
do_mystuff
after $::delay repeat
}

looses its stride when [do_mystuff] errors out.
the effective period will be expanded by the
runtime use of [do_mystuff]

A good [repeat] implementation would use catch to run the payload.
proc repeat {} {
catch do_mystuff cerr
after $::delay repeat
}

proc repeat2 {} {
after $::delay
do_mystuff
}

Will keep to the given period but has dangers when the runtime for
the payload exceeds the delay.

To close:
There is a comfortable jobscheduling function in Scotty.
( it has the period elongation problem too )

uwe

Stuart

unread,
Jun 12, 2012, 7:16:52 PM6/12/12
to
Thanks for the replies.

Yours,

Stuart

hridayd...@gmail.com

unread,
Mar 25, 2013, 5:33:29 AM3/25/13
to
I need to repeat a function which has a for loop inside it...

proc Repeat {} {
global ns val(nn)
# now set up some events
for {set i 0} {$i < $val(nn)} {incr i} {
$ns at 0.1 "$a($i) send_message 200 $i {echo} $MESSAGE_PORT"
$ns at 1.0 "finish"
}


# Repeat after 30minutes have elapsed'

after 100 Repeat
}

This is not repeating.. Please help..

Arjen Markus

unread,
Mar 25, 2013, 6:21:16 AM3/25/13
to
Op maandag 25 maart 2013 10:33:29 UTC+1 schreef hridayd...@gmail.com het volgende:
Are you sure the event loop is running? That is:
- You are using wish (automatic)
- You are using vwait for a variable (you have to explicitly add
that command to your code)
- (Almost trivial) you do call [Repeat]

Regards,

Arjen

Robert Heller

unread,
Mar 25, 2013, 6:34:56 AM3/25/13
to
Is this with wish or tclsh?

If tclsh, have you called vwait?

The 'after nnn code' only works if the event loop is running and gets
entered. Wish (or 'package require Tk') fires up the event loop. Tclsh
*by itself* does not. Calling vwait in tclsh, starts and enters the
event loop.
--
Robert Heller -- 978-544-6933 / hel...@deepsoft.com
Deepwoods Software -- http://www.deepsoft.com/
() ascii ribbon campaign -- against html e-mail
/\ www.asciiribbon.org -- against proprietary attachments



Uwe Klein

unread,
Mar 25, 2013, 5:57:28 AM3/25/13
to
hridayd...@gmail.com wrote:
> I need to repeat a function which has a for loop inside it...
>
> proc Repeat {} {
> global ns val(nn)
global ns val ;# the array is in global context not the array element
> # now set up some events
> for {set i 0} {$i < $val(nn)} {incr i} {
> $ns at 0.1 "$a($i) send_message 200 $i {echo} $MESSAGE_PORT"
where do you get array 'a' from?
> $ns at 1.0 "finish"
> }
>
>
> # Repeat after 30minutes have elapsed'
>
> after 100 Repeat
> }
>
> This is not repeating.. Please help..

does the event loop run?
i.e. are you either using wish
or the plain shell and some command
that activates it like [vwait ...

uwe

Uwe Klein

unread,
Mar 25, 2013, 6:02:43 AM3/25/13
to
changes to have it run in tclsh:

set val(nn) 2
set a(0) 100
set a(1) 200
set a(2) 300
set a(3) 400
set ns myproc
set MESSAGE_PORT 1234
set ::cnt 0

proc myproc args {
puts stderr [ concat $args ]
}

proc Repeat {} {
# global ns val(nn)
global ns val a MESSAGE_PORT
# now set up some events
for {set i 0} {$i < $val(nn)} {incr i} {
$ns at 0.1 "$a($i) send_message 200 $i {echo} $MESSAGE_PORT"
$ns at 1.0 "finish"
}

# debug:
puts stderr cnt:$::cnt
# Repeat after 30minutes have elapsed'

after 100 Repeat
incr ::cnt
}

Repeat
vwait forever

# end

uwe

Donald Arseneau

unread,
Mar 25, 2013, 7:57:16 AM3/25/13
to
Good bug fixing Uwe.

Only problem now is that 100 ms is a little bit smaller than 30 min :-)


--
Donald Arseneau as...@triumf.ca

Uwe Klein

unread,
Mar 25, 2013, 9:15:04 AM3/25/13
to
Har!
my assumption was that the 100ms delay was the first debug step.

uwe
0 new messages