1 Functional GUIs

In the context of a course on programming with algebra,How to Design Programs [2nd ed] a teacher may ask a programming novice to solve the following problem:

Your game needs a circle that shrinks every time the player manipulates the mouse or presses a key. Design a program that illustrates this behavior.

Using the 2htdp/universe and 2htdp/image libraries, the student may come up with the main function in the left column:
(require 2htdp/image)
(require 2htdp/universe)
 
; type State is Nat
 
(define (main)
  (big-bang
     ; initial state:
     10
     [to-draw render
              220
              220]
     [on-mouse less1]
     [on-key less1]))
(require 2htdp/image)
 
 
; type State is Nat
 
(define (main)
  (send (new world%
           [state0 10]
           [to-draw render]
           [width 220]
           [height 220]
           [on-mouse less1]
           [on-key less1])
        start))
Roughly speaking, big-bang is a state-machine. The programmer specifies an initial state, a bunch of event handlers, and a function that renders the current state as an image. Each event handler accepts big-bang’s current state plus event-specific information; it returns a new state, which big-bang squirrels away. Here the initial state is 10, and as figure 1 shows, both the mouse and the key event handler subtract 1 from the current state, regardless of what event they process. The to-draw clause specifies render as the function that expresses big-bang’s current state as an image and that this images is supposed to be displayed on a 220 x 220 pixels canvas.

The 2htdp/universe library compiles the student’s program to (roughly) the code in the right column. Since Racket’s GUI API relies on the class system, the main function creates an instance of a class called world%,By convention, a variable with a name ending in % stands for a class. handing along big-bang’s keyword arguments (after some parsing) as keyword arguments to new; when the object is created and initialized, main calls the object’s start method.

; Nat Any* -> Nat
; subtract 1 from the current state,
; regardless of the event
(define (less1 cd . other)
 (- cd 1))
 
; Nat -> Image
; render cd as a red circle
(define (render cd)
 (define r (if (>= cd 0) cd 0))
 (circle (+ 10 (* 10 r)) "solid" "red"))

Figure 1: Rendering and event-handling functions

The rest of this essay explains how the world% class functions. What the interested reader has to know about the big-bang mechanics is that while the initial state value and the to-draw clauses are mandatory, the on-mouse and on-key clause are optional.Another optional big-bang clause is on-tick, which runs a handler every time the clock ticks. If a student omits either clause, main does not handle mouse clicks or key presses. In contrast, the to-draw clause is mandatory and so is the specification of an initial state. The programmer may pick any set of values as the state space; students are expected to specify the state space in a comment, such as the one in the 2-column code sample above.