Tickers in Racket

Our first example demonstrates the use of tickers in Racket. Tickers are used when you want to perform an action repeatedly at regular intervals. Here’s an implementation of a ticker that ticks periodically until we stop it.

#lang racket

(require racket/async-channel)

(define (main)
  ; Create a ticker that ticks every 500 milliseconds
  (define ticker (make-ticker 500))
  (define done-ch (make-async-channel))

  ; Start a thread to handle the ticker
  (thread
   (λ ()
     (let loop ()
       (match (sync/timeout 0 done-ch ticker)
         ['done (void)]  ; Exit if 'done signal received
         [(? date? t) (printf "Tick at ~a~n" t) (loop)]
         [_ (loop)]))))

  ; Let the ticker run for 1600 milliseconds
  (sleep 1.6)
  
  ; Stop the ticker
  (ticker-stop! ticker)
  (async-channel-put done-ch 'done)
  (printf "Ticker stopped~n"))

; Helper function to create a ticker
(define (make-ticker interval-ms)
  (define ch (make-async-channel))
  (define stop? #f)
  (thread
   (λ ()
     (let loop ()
       (unless stop?
         (async-channel-put ch (current-date))
         (sleep (/ interval-ms 1000.0))
         (loop)))))
  (λ () 
    (if stop?
        (sync never-evt)
        (sync/timeout 0 ch))))

; Helper function to stop a ticker
(define (ticker-stop! ticker)
  (set! stop? #t))

(main)

In this Racket implementation:

  1. We define a make-ticker function that creates a ticker. It uses an asynchronous channel to send tick events.

  2. The main function creates a ticker that ticks every 500 milliseconds.

  3. We start a thread that listens for tick events and prints the current time for each tick.

  4. After 1600 milliseconds, we stop the ticker and signal the listening thread to exit.

  5. The ticker-stop! function is used to stop the ticker.

When we run this program, the ticker should tick 3 times before we stop it.

$ racket tickers.rkt
Tick at #<date Sun Feb 23 11:29:56 -0700 2024>
Tick at #<date Sun Feb 23 11:29:56 -0700 2024>
Tick at #<date Sun Feb 23 11:29:57 -0700 2024>
Ticker stopped

This example demonstrates how to create and use tickers in Racket, which can be useful for various timing and scheduling tasks in your programs.