I ran across a scoping puzzle while experimenting with ScheduledTasks, and I'd be grateful for an explanation from the sages here. I found a workaround by intuitive horse sense, but was unable to explain to myself adequately what was wrong with my original attempt.
First, a straightforward, tail-recursive, synchronous Module
Module[{state = 0, doNextIteration},
doNextIteration = Function[
state = state + 1;
If[state < 4,
(Print[state]; doNextIteration[])]];
doNextIteration[]]
(* 1 2 3 *)
Next, my first attempt to do the same with asynchronous tasks, which I need to tail-chain as one-shot ScheduledTasks. If CreateScheduledTask has a second List
argument, then it creates a one-shot task delayed by the time in seconds in the list, just what I need for my bigger application. In this simplified sample, the ScheduledTask tail-chains a new one-shot ScheduledTask by a tail-recursive call -- just like the successful synchronous code -- once every tenth of a second until the condition on state
produces False (ignore cleanup of the task objects for simplicity, here).
Module[{state = 0, runNextTask},
runNextTask = Function[
StartScheduledTask@
CreateScheduledTask[
state = state + 1;
If[state < 4,
(Print[state]; runNextTask[])],
{0.10}]];
runNextTask[]]
OK, the problem is this only Prints once, not the desired three times. I had a sickening hunch that the problem has something to do with runNextTask
being local to the Module
and somehow not being able to refer to itself recursively -- even though there is only one Module
-- in the bizzaro-land of asynchrony, so I "fixed" the code as follows:
Module[{state = 0, runNextTask = Unique[]},
runNextTask[] :=
If[state < 3,
StartScheduledTask@
CreateScheduledTask[
Module[{},
state = state + 1;
Print[state];
runNextTask[]],
{0.10}]];
runNextTask[]]
I made runNextTask
refer to a Unique global symbol, and made my function into a rewrite rule attached to runNextTask[]
. This works great, but I don't understand well why it does. I hate being as dumb as a horse, even if I can jump the fences.
Clues, advice, explanations: all appreciated.