Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

In version 7 there exist these Internal` context functions:

?Internal`*Periodical*

AddPeriodical   Periodicals   RemovePeriodical   $ThisPeriodical

In a comment to this answer Szabolcs stated that these "seem to provide very similar (the same?) functionality" to ScheduledTasks in version 8.

  • How do I use them?

  • To what extent is is possible to mimic version 8 functionality using these?

share|improve this question
    
FYI: the Accepted answer causes v7 to randomly crash but that's probably unavoidable and the reason these functions weren't ready for prime-time in that release. –  Mr.Wizard Aug 14 '13 at 16:32
add comment

2 Answers 2

up vote 5 down vote accepted

You can turn this then into a package, and change the lower-case to uppercase... Hope it works well enough for your goals. If not, we'll improve it in time

AppendTo[$ContextPath, "Internal`"];

ClearAll["`private`*"];
SetAttributes[`private`count, HoldRest];
`private`count[_, expr_, count_Symbol][id_, ___] /; 
  Block[{$scheduledTask = `private`getST[id]}, expr; ++count]/;False := Null
e : `private`count[i_, _, count_Symbol][id_, endFun : _ : (Null &)] /;
   count === i := (Remove[count]; RemovePeriodical[e]; endFun[])
`private`count[___][___] := Null

`private`getST[id_] /; 
  MemberQ[scheduledTasks[], scheduledTaskObject[id, ___]] := 
 First@Cases[scheduledTasks[], scheduledTaskObject[id, ___]]
`private`getST[_] := $Failed;

`private`STQ[scheduledTaskObject[id_, expr_, time_, start_, _]] := 
 Length[Cases[scheduledTasks[]/. HoldPattern@\[Infinity] -> \[Infinity], 
    scheduledTaskObject[id, expr, time, start, _]/. HoldPattern@\[Infinity] -> \[Infinity]]] >= 1
`private`STQ[___] := False;

`private`startScheduledTask[
   st : scheduledTaskObject[id_, 
     expr_, {time_, count_}, (start_ /; start <= AbsoluteTime[]) | 
      Automatic, _]] := 
  Module[{counter = 0}, ClearAttributes[counter, Temporary];
   AddPeriodical[`private`count[count, expr, counter][
     id, `private`startStop[id, False] &], time]];

`private`startScheduledTask[
  st : scheduledTaskObject[id_, expr_, {time_, count_}, start_, _]] :=
  start - AbsoluteTime[] /. 
  remaining_ :> 
   With[{pst := `private`startScheduledTask[
       scheduledTaskObject[
        "", `private`startScheduledTask[
         scheduledTaskObject[id, expr, {time, count}, Automatic, 
          False]], {remaining, 1}, Automatic, 
        False]]}, `private`extraTasks[id] = Hold[pst]; pst]

ClearAll[createScheduledTask, startScheduledTask, 
  stopScheduledTask, $scheduledTask, removeScheduledTask, 
      scheduledTasks, scheduledTaskObject, runScheduledTask];
    $scheduledTask::usage = ""; scheduledTaskObject::usage = "";
SetAttributes[{createScheduledTask, runScheduledTask}, HoldFirst];
SetAttributes[scheduledTaskObject, HoldAll];
SetAttributes[{stopScheduledTask, removeScheduledTask}, Listable];


scheduledTasks[] = {}; `private`idCounter = 0;
`private`startStop[st : (sto : scheduledTaskObject)[__], 
   b : True | False] := st /. sto[rest__, _] :> sto[rest, b];
`private`startStop[id_Integer, b : True | False] := 
  scheduledTasks[] = 
   scheduledTasks[] /. 
    e : scheduledTaskObject[id, rest__] :> `private`startStop[e, b];

createScheduledTask[expr_, {time_, count_: 1}, 
   start_: Automatic] := ++`private`idCounter /. 
    c_ :> scheduledTaskObject[c, expr, {time, count}, start, 
      False] /. sto_ :> (AppendTo[scheduledTasks[], sto]; sto);

createScheduledTask[expr_, time_: 1, rest___] := 
  createScheduledTask[expr, {time, \[Infinity]}, rest];

startScheduledTask[
  st : scheduledTaskObject[
     id_, __]?`private`STQ] := (`private`startStop[id, 
   True]; `private`startScheduledTask[st]; Null /; False)
startScheduledTask[s_] := s;

stopScheduledTask[
  st : scheduledTaskObject[id_, 
     expr_, {time_, 
      count_}, __]?`private`STQ] := (Periodicals[] /. {HoldForm[
      i : `private`count[sth__][id, __]] :> 
     Quiet@RemovePeriodical[i]}; `private`extraTasks[id] /. 
   Hold[`private`startScheduledTask[
      scheduledTaskObject[_, e_, ___]]] :> Quiet@RemovePeriodical[e];
  Quiet[`private`extraTasks[id] =.];
  `private`startStop[id, False]; Null /; False)

stopScheduledTask[st_] := st;

runScheduledTask[stuff___] := 
  startScheduledTask@createScheduledTask@stuff~`private`startStop~True;

removeScheduledTask[
  st : scheduledTaskObject[
     id_, __]?`private`STQ] := (stopScheduledTask[st]; 
  scheduledTasks[] = (DeleteCases[scheduledTasks[], 
     scheduledTaskObject[id, __]]); st)
removeScheduledTask[_] := $Failed;

In case you are interested to copy or as reference, here go the usage messages

ToExpression[#, InputForm, Function[name, name::usage, HoldAll]] & /@ 
 Names["System`*Sche*"]

returns, copied as plain text

{CreateScheduledTask[expr] creates a task that will repeatedly evaluate expr once per second.
CreateScheduledTask[expr,time] creates a task that will repeatedly evaluate expr every time seconds.
CreateScheduledTask[expr,{time}] creates a task that will evaluate expr once after time seconds.
CreateScheduledTask[expr,{time,count}] creates a task that will try evaluating expr once every time seconds up to count times total.
CreateScheduledTask[expr,timespec,start] creates a task that will evaluate expr according to timespec starting at start time.,RemoveScheduledTask[obj] remove the obj from the list of currently set tasks.,ResetScheduledTask[obj] resets scheduled task object obj to the original parameter values.
ResetScheduledTask[obj,timespec]  resets scheduled task timing to timespec.
ResetScheduledTask[obj,timespec,offset] resets scheduled task time offset to offset.,RunScheduledTask[expr] schedules and starts a task that will repeatedly evaluate expr once per second.
RunScheduledTask[expr,time] schedules and starts a task that will repeatedly evaluate expr every time seconds.
RunScheduledTask[expr,{time}] schedules and starts a task that will evaluate expr once after time seconds.
RunScheduledTask[expr,{time,count}] schedules and starts a task that will try evaluating expr once every time seconds up to count times.
RunScheduledTask[expr,timespec,start] schedules a task that will automatically start at start time.,ScheduledTaskObject[id,expr,spec,...]  is a task object specifying future evaluation of expr according to spec.,ScheduledTasks[]  returns a list of ScheduledTaskObject expressions that represent current tasks.,StartScheduledTask[obj] starts the task represented by obj.,StopScheduledTask[obj] deactivates the task obj.,$ScheduledTask returns the current ScheduledTaskObject. }
share|improve this answer
    
Please still test it. I just made the code of yesterday a little bit neater –  Rojo Jul 15 '12 at 16:51
    
I really wanted your work to pay off but unfortunately I still got a crash. :-/ I shall try to find a way to repay your efforts on this. –  Mr.Wizard Aug 11 '12 at 14:22
    
@Mr.Wizard forget about it. But you could give the question I just posted a shot ;D –  Rojo Aug 11 '12 at 14:30
    
@Mr.Wizard why accept this after so long? –  Rojo Aug 14 '13 at 18:31
    
I was looking through my list of questions to see if there was anything I forgot to Accept, and this time it struck me that there wasn't likely a better answer possible. Just as one might Accept "it's a bug, fixed in the next version" I should Accept this. Unlike some of my other questions that I am still hoping will be addressed either by some new insight or a future version this one is specific to v7 and you gave it a great effort. Basically I should have Accepted it before but I was just annoyed that the answer was "no, it won't work because these functions are buggy." –  Mr.Wizard Aug 14 '13 at 22:07
add comment

As a starting point I'll write up what I found about these functions before. I'm hoping someone will take a better look at them and will write a more complete answer.


Spelunking in version 8,

Internal`AddPeriodical[Print["boo!"], 3]

Now you get a boo! every 3 seconds.

Internal`Periodicals[]

(* ==> {Print["boo!"]} *)

Now do

Internal`RemovePeriodical[Print["boo!"]]

to stop it.

Internal`Periodicals[]

(* ==> {} *)

Note that AddPeriodical and RemovePeriodical have HoldFirst.

Internal`$ThisPeriodical seems to be undefined during normal evaluations, while it is set to the currently executing periodical (wrapped in HoldForm) when a periodical is being executed.

Most (all?) of the version 8 functionality seems to be implementable in terms of these, provided that they work the same way in version 7 as in 8 (which I cannot test).

share|improve this answer
4  
Or, more annoyingly: Internal`AddPeriodical[Speak["boo!"], 3] but just be sure you're ready to invoke Internal`RemovePeriodical[Print["boo!"]] before going nuts! –  murray Mar 11 '12 at 22:08
1  
@murray Nooo, you have to do Internal`RemovePeriodical[Speak["boo!"]] –  Ajasja Jul 16 '12 at 7:58
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.