I would like to present a very simple example of animation in this chapter that makes use of higher-order functions. Please click here for a quick demo of this example.
Intuitively, animation can be performed by calling the following function animate:
// extern fun sleep(ms: int): void extern fun animate(fwork: cfun(void)): void // (* ****** ****** *) // implement animate(fwork) = { val () = fwork() val () = sleep(N(*ms*)) val () = animate(fwork) } //
Clearly, calling sleep prevents programs from being executed concurrently. Instead, let us combine sleep and animate into one function of the name sleep_animate:
// extern fun sleep_animate (ms: int, fwork: cfun(void)): void // (* ****** ****** *) // implement animate(fwork) = { val () = fwork() val () = sleep_animate(N(*ms*), fwork) } //
Let us generalize sleep_animate to the following function execute_after:
// extern fun execute_after (fwork: cfun(void), ms: int): void // (* ****** ****** *) // implement sleep_animate(ms, fwork) = execute_after(lam() => animate(fwork), ms) //
If we target JS, then the function execute_after can be implemented as follows:
// implement execute_after (fwork, ms) = ( // $extfcall (void, "setTimeout", cloref2fun0(fwork), ms) // ) (* end of [execute_after] *) //
As an example, please find the ATS source in DigitClock.dats for a digital clock directly based on animate. And please click here for a demo of the digital clock.
Given N, fwork, and ms, the following function repeat_execute_after executes the calls fwork(i) for i ranging from 0 to N-1 and then repeats:
// extern fun repeat_execute_after ( N: int, fwork: (int) -> void, ms: int) : void = "mac#" // implement repeat_execute_after ( N, fwork, ms ) = let // fun auxmain(i: int): void = if i >= N then auxmain(0) else (fwork(i); execute_after(lam() => auxmain(i+1), ms)) // in auxmain(0) end // end of [repeat_execute_after] //
Please find on-line the entirety of the code used in this chapter. The mentioned URL link(s) can be found as follows: