Lab 6

Pair Programming

We practise pair programming. Each pair works on one machine. One member of the team is the pilot and the other the co-pilot. The pilot makes the calls and the co-pilot asks the pilot to justify his/her decisions. The pilot types the code and the co-pilot checks. Switch roles often.

Design Recipe

Remember to always follow the design recipe.

Program Aesthetics

... programs must be written for people to read, and only incidentally for machines to execute. - SICP

A program is a product usually used over and over again. Other programmers or even your self may want to modify or extend your program, or fix a bug. So programs must be readable, in order to understand easily and quickly how they work. An important part of programs readability is good coding style.

Guidelines for good style

Guideline 1: Break Lines

Consider the data definition for Time:

(define-struct time (hours minutes))
;; A Time is (make-time Number Number)
Consider this program:
;; Time -> Image
;; Produce an image of the given time, as it appears on a digital clock.
(define (time->text a-time)
  (text (string-append (number->string (time-hours a-time)) ":" (cond [(< (time-minutes a-time) 10) "0"]
  [else ""]) (number->string (time-minutes a-time))) 30 'red))
  1. How many arguments are there to text?
  2. How many cond clauses are there?
  3. What are the arguments to string-append?
This code is a disaster. Because the body is squeezed onto two lines, we cannot answer these questions at a glance. If we insert line breaks, the code becomes much more readable.
;; Time -> Image
;; Produce an image of the given time, as it appears on a digital clock.
(define (time->text a-time)
  (text (string-append (number->string (time-hours a-time))
                       ":"
                       (cond 
                         [(< (time-minutes a-time) 10) "0"]
                         [else ""])
                       (number->string (time-minutes a-time)))
        30
        'red)
With this code, it is easy to see the three arguments to text , the four strings being appended, and the two cond clauses.

In general, try to break long lines by

If even these formatting hints do not help, consider designing and using a helper function to make the code more compact. For example, in time->text above, it's probably a good idea to "factor out" the (string-append ..) expression as a separate helper function.

Attention: Every line of code should be no more than 80 characters long. The homework server will reject submissions when they contain a line with more than 80 characters.

Exercise: Rewrite time->text by developing and using a helper function that computes the (string-append ...) portion of the body. Be sure to invent a good name for this helper function.

Guideline 2: Indentatation

Consider the following program:

;; LOS -> Number
;; Determine how many symbols are in a-los
(define (count a-los)
  (cond
[(empty? a-los) 0]
 [(cons? a-los)
  (+ 1 (count (rest a-los)))]))
This is not indented properly. Copy and paste this code into DrScheme. Then, in DrScheme, select Reindent All under the Scheme menu. DrScheme will indent the code properly automatically! Make good use of this feature as you develop your programs. Also note that the tab key can be used to automatically indent just the line that the cursor is on. Indentation is a very important factor of readability because it denotes the structure of the program at a glance. Expressions of the program that are part of the same larger expression begin usually at the same column of the code.

Attention: When you use the Reindent All feature or the tab key, your code might appear differently than you expect. This usually means that your program is mis-parenthesized. Move the cursor through your code and use the grey highlighting to be sure that your parentheses are matched as you intend.

Guideline 3: Parentheses Layout

Let's reconsider count from above. The indentation is technically correct, but the parentheses are arranged a bit differently:

;; LOS -> Number
;; Determine how many symbols are in a-los
(define (count a-los)
  (cond
    [(empty? a-los) 0
    ]
    [(cons? a-los)
     (+ 1 (count (rest a-los))
     )
    ]
   )
)
A programmer who arranges their parentheses like this is probably trying to use the vertical alignment of the open and closing parentheses to visually determine the code structure. It is much easier to compress the closing parentheses together, and then eyeball the program structure using its indentation. When you need to match parentheses visually, use DrScheme's grey highlighting instead.
;; LOS -> Number
;; Determine how many symbols are in a-los
(define (count a-los)
  (cond
    [(empty? a-los) 0]
    [(cons? a-los)
     (+ 1 (count (rest a-los)))]))
Proper indentation and parentheses placement render the parentheses and brackets nearly invisible to the trained eye.

DrScheme: The Operating System of Choice for Beginning Hackers

An operating system (OS) is a program that listens to and reacts to the "environment" all the time. When anything of interest happens, the OS takes some action or may ask another program to react by calling it on some input. These "things of interest" are called events, and when the OS calls another program, it passes in some information about the relevant event. The programmer must provide functions that the OS will use to respond to events. These are typically referred to as event handlers. The OS will not use our programs as event handlers by default. We must explicitly instruct the OS to do so. The process of telling the OS to use our program as an event handler is referred to as registering an event handler.

Our operating system is DrScheme. Actions that matter are clock ticks, keystrokes, and mouse movements and clicks. Each of these actions causes events to which DrScheme may react.

  1. Clock ticks are events.
  2. A keystroke generates two separate events: the key press and the key release. Events caused by a keystroke are called KeyEvents, and the Help Desk documentation for on-key-event contains a data definition for KeyEvent.
  3. There are several kinds of mouse events because we use the mouse in various ways. For example, we may click, drag, move the mouse into a window, or move the mouse out of a window. Search the Help Desk for on-mouse-event for a data definition describing mouse events.
You should also note that the OS reacts to events in a sequential manner. It may appear to react to clock ticks and key events simultaneously, but what really happens is that the OS processes one first and then the other. The computer just does this so quickly that it appears to us as though the events are handled at the same time.

Finally, the OS does one more useful thing: it keeps track of information that might change from event to event. We typically refer to this information that may change as "the state" or "the world" in our case. We typically represent the world as an instance of some structure that contains several pieces of data (such as the position and velocity of a rocket). When the OS reacts to an event by calling a program, it also passes in the world to that program. When that program produces a new world, the OS will hang onto it and use it to handle subsequent events.

With all these interesting things happening, it sure would be nice to see the results of the computer's labor. On top of all of the event handling, the OS gives us a way to view the progress of the computation at any point in time. We can write a function that interprets the data in the world and produces, say, an image. We can then ask the OS to call our function every time the world changes, and the OS will draw the result into a window so that we can see it. If we arrange for the world to change several times per second (using the clock tick events), then we can create an animation or a movie.

To write animations and interactive programs like the rocket launch, the UFO game, or the Worm game, we just need to write programs that react to clock ticks, keystrokes, and the mouse. We then register our programs as event handlers. We also tell the OS how often we want the clock to tick, what the initial world is, and how big the drawing window is. As you know already, DrScheme provides several built-in functions that enable us to register our event handlers:

Search Help Desk for world.ss to see formal contracts and purpose statements for each of these functions.

Exercise 2

Design a function that draws a circle on the canvas and permits the user to interact with it. When the mouse is clicked, the circle moves to the location of the mouse click. The up and down arrow keys grow and shrink the radius of the circle, respectively.

Exercise 3

Use the rest of the lab time to work on your homework assignment. Remember, the tutors are right there: take advantage of this time to ask them questions.