... 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.
Consider the data definition for Time:
Consider this program:(define-struct time (hours minutes)) ;; A Time is (make-time Number Number)
;; 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))
text
?cond
clauses are there?string-append
?With this code, it is easy to see the three arguments to;; 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)
text
, the four strings being appended, and the two cond
clauses.
In general, try to break long lines by
cond
clause its own line. [Always a good idea.]cond
question or answer is long, then
start the answer on the next line. [Often a good idea.]string-append
is a typical offender.]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.
Consider the following program:
This is not indented properly. Copy and paste this code into DrScheme. Then, in DrScheme, select;; 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)))]))
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.
Let's reconsider count
from above. The indentation is technically correct, but the parentheses are arranged a bit differently:
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.;; 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)))]))
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.
KeyEvent
s, and the Help Desk documentation for on-key-event
contains a data definition for KeyEvent
.on-mouse-event
for a data definition describing mouse events.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:
big-bang
: Tells the OS how big the drawing window is, how often the clock should tick, and what the initial world is.on-tick-event
: Tells the OS to call the given function in response to a clock tick.on-key-event
: Tells the OS to call the given function in response to a key event.on-mouse-event
: Tells the OS to call the given function in response to a mouse event.on-redraw
: Tells the OS to call the given function to produce an image of the world whenever it changes. The OS will automatically draw the resulting image into the drawing window.world.ss
to see formal contracts and purpose statements for each of these functions.
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.