The input of a function is seldom a single measurement (number), a single switch position (boolean), or a single name (symbol). Instead, it is almost always a piece of data that represents an object with many properties. Each property is a piece of information. For example, a function may consume a record about a CD; the relevant information might include the artist's name, the CD title, and the price. Similarly, if we are to model the movement of an object across a plane with a function, we must represent the position of the object in the plane, its speed in each direction, and possibly its color. In both cases, we refer to several pieces of information as if they were one: one record and one point. In short, we COMPOUND several pieces of data into a single piece of data.
Scheme provides many different methods for compounding data. In this section, we deal with structures. A structure combines a fixed number of values into a single piece of data. In section 9, we will encounter a method for combining an arbitrarily large number of values into a single piece of data.
Structures 
Suppose we wish to represent the pixels (colored dots) on our computer monitors. A pixel is very much like a Cartesian point. It has an x coordinate, which tells us where the pixel is in the horizontal direction, and it has a y coordinate, which tells us where the pixel is located in the downwards vertical direction. Given the two numbers, we can locate a pixel on the monitor, and so can a computer program.
DrScheme's teachpacks represent pixels with posn
structures. A
posn
structure combines two numbers. That is, a posn
is
a single value that contains two values. We can create a posn
structure with the operation makeposn
, which consumes two
numbers and makes a posn
. For example,
(makeposn 3 4) (makeposn 8 6) (makeposn 5 12)
are posn
structures. Each of these structures has the same status
as a number as far as computations are concerned. Both primitive
operations
and functions can consume and produce structures.
Now consider a function that computes how far some pixel is from the origin. The contract, header, and purpose statement are easy to formulate:
;;distanceto0 : posn > number
;; to compute the distance ofaposn
to the origin (define (distanceto0 aposn) ...)
In other words, distanceto0
consumes a single value, a
posn
structure, and produces a single value, a number.
We already have some input examples, namely, the three posn
structures mentioned above. What we need next are examples that relate
inputs and outputs. For points with 0
as one of the coordinates,
the result is the other coordinate:
(distanceto0 (makeposn 0 5)) = 5 and (distanceto0 (makeposn 7 0)) = 7
In general, we know from geometry that the distance from the origin to a
position with coordinates x
and y
is distance
Thus,
(distanceto0 (makeposn 3 4)) = 5 (distanceto0 (makeposn 8 6)) = 10 (distanceto0 (makeposn 5 12)) = 13
Once we have examples, we can turn our attention to the definition of the
function. The examples imply that the design of distanceto0
doesn't need to distinguish between different situations. Still, we are
stuck now, because distanceto0
has a single parameter that
represents the entire pixel but we need the two coordinates to compute the
distance. Put differently, we know how to combine two numbers into a
posn
structure using makeposn
and we don't know how to
extract these numbers from a posn
structure.
Scheme provides operations for extracting values from
structures.^{18} For posn
structures, Scheme
supports two such operations: posnx
and posny
. The
former operation extracts the x coordinate; the latter extracts the
y coordinate.
To describe how posnx
, posny
, and makeposn
are related, we can use equations that are roughly analogous to the
equations that govern addition and subtraction:
(posnx (makeposn 7 0)) = 7
and
(posny (makeposn 7 0)) = 0
The equations only confirm what we already know. But suppose we introduce the following definition:
(define aposn (makeposn 7 0))
Then we can use the two operations as follows in the Interactions window:
(posnx aposn) = 7 (posny aposn) = 0
Naturally, we can nest such expressions:
(* (posnx aposn) 7) = 49 (+ (posny aposn) 13) = 13
Now we know enough to complete the definition of distanceto0
. We
know that the function's aposn
parameter is a posn
structure and that the structure contains two numbers, which we can extract
with (posnx aposn)
and (posny aposn)
. Let us add
this knowledge to our function outline:
(define (distanceto0 aposn) ... (posnx aposn) ... ... (posny aposn) ...)
Using this outline and the examples, the rest is easy:
(define (distanceto0 aposn) (sqrt (+ (sqr (posnx aposn)) (sqr (posny aposn)))))
The function squares (posnx aposn)
and (posny aposn)
,
which represent the x and y coordinates, sums up the results, and takes
the square root. With DrScheme, we can also quickly check that our new
function produces the proper results for our examples.
Exercise 6.1.1. Evaluate the following expressions:
(distanceto0 (makeposn 3 4))
(distanceto0 (makeposn (* 2 3) (* 2 4)))
(distanceto0 (makeposn 12 ( 6 1)))
by hand. Show all steps. Assume that sqr
performs its
computation in a single step. Check the results with DrScheme's
stepper.
Solution
Drawing 
DrScheme provides the graphics teachpack draw.ss, which introduces simple graphics operations:
drawsolidline
, which consumes two posn
structures, the beginning and the end of the line on the canvas, and a
color.
drawsolidrect
, which consumes four arguments:
a posn
structure for the upperleft corner of the rectangle,
a number for the width of the rectangle, another number for its height, and
a color.
drawsoliddisk
, which consumes three arguments:
a posn
structure for the center of the disk, a number for the
radius of the disk, and a color.
drawcircle
, which consumes three arguments:
a posn
structure for the center of the circle, a number for the
radius, and a color.
Each of the operation produces true
, if it succeeds in changing
the canvas as specified. We refer to the action to the canvas as an
EFFECT,
but we will ignore studying the precise nature of effects
until part VII. Also, if anything goes wrong with the
operation, it stops the evaluation
with an error.
Each drawing operation also comes with a matching clear
operation: clearsolidline
, clearsolidrect
,
clearsoliddisk
, and clearcircle
. If these functions
are applied to the same arguments as their matching draw
function, they clear the corresponding shapes of the
canvas.^{19}
Drawing operations on computers interpret the screen as follows:
Drawing 
Exercise 6.2.1. Evaluate the following expressions in order:
(start 300 300)
, which opens a canvas;
(drawsolidline (makeposn 10 10) (makeposn 110 10) 'red)
, which
draws a red line close to, and parallel to, the upper end of the canvas;
(drawsolidrect (makeposn 10 30) 100 50 'blue)
, which draws
a blue rectangle of width 100 and height 50 parallel to the red line;
(drawcircle (makeposn 110 30) 30 'yellow)
, which draws a yellow
circle of radius 30 centered at the upper right corner of the rectangle;
(drawsoliddisk (makeposn 10 80) 50 'green)
, which draws a
green disk of radius 50 centered at the lower left corner of the rectangle;
and
(stop)
, which closes the canvas.
Read the documentation for draw.ss in DrScheme's HelpDesk.
The definitions and expressions in figure 8 draw a traffic light. The program fragment illustrates the use of global definitions for specifying and computing constants. Here, the constants represent the dimensions of the canvas, which is the outline of the traffic light, and the positions of three light bulbs.
Exercise 6.2.2.
Develop the function clearbulb
. It consumes a symbol that denotes
one of the possible colors: 'green
, 'yellow
, or
'red
, and it produces true
. Its effect is ``to turn off''
the matching bulb in the traffic light. Specifically, it should clear the
disk and display a circle of the matching color instead.
Choice of Design Recipe: See section 5 for designing functions that consume one of an enumeration of symbols.
Testing: When testing functions that draw shapes into a canvas, we ignore test expressions. Although it is possible to implement appropriate test suites, the problem is beyond the scope of this book.
Combining Effects: The primitive operations
for drawing and
clearing disks and circles produce true
if they successfully
complete their task. The natural way to combine the values and the effects
of these functions is to use an andexpression.
In particular, if
exp1
and exp2
produce effects and we wish to see the
effects of exp2
after those of exp1
, we write
(and exp1 exp2)
Later we will study effects in more detail and learn different ways to combine effects. Solution
Exercise 6.2.3.
Develop a function drawbulb
. It consumes a symbol that denotes
one of the possible colors: 'green
, 'yellow
, or
'red
, and produces true
. Its effect is ``to turn on'' the
matching bulb in the traffic light.
Solution
Exercise 6.2.4.
Develop the function switch
. It consumes two symbols, each of
which stands for a traffic light color, and produces true
. Its
effects are to clear the bulb for the first color and then to draw the
second bulb.
Solution
Exercise 6.2.5.
Here is the function next
:
;; next : symbol > symbol
;; to switch a traffic light's current color and to return the next one
(define (next currentcolor)
(cond
[(and (symbol=? currentcolor 'red) (switch 'red 'green))
'green]
[(and (symbol=? currentcolor 'yellow) (switch 'yellow 'red))
'red]
[(and (symbol=? currentcolor 'green) (switch 'green 'yellow))
'yellow]))
It consumes the current color of a traffic light (as a symbol) and produces
the next color that the traffic light shows. That is, if the input is
'green
, it produces 'yellow
; if it is 'yellow
,
it produces 'red
; and if it is 'red
, it produces
'green
. Its effect is to switch the traffic light from the input
color to the next color.
Replace the last three lines of the program fragment in
figure 8 with (drawbulb 'red)
. This creates
a traffic light that is red. Then use next
to switch the traffic
light four times.
Solution
In the preceding section we explored one particular class of structures:
the posn
structures. A posn
structure combines two
numbers, and it is useful to represent pixels. If we wish to represent
employee records or points in threedimensional space, however,
posn
s are useless. DrScheme therefore permits programmers to
define their own structures so that they can represent all kinds of
objects with a fixed number of properties.
Using and Defining Structures 
A STRUCTURE DEFINITION
is, as the term says, a new form of
definition. Here is DrScheme's definition of posn
:
(definestruct posn (x y))
When DrScheme evaluates this structure definition, it creates three operations for us, which we can use to create data and to program:
makeposn
, the CONSTRUCTOR,
which creates
posn
structures;
posnx
, a SELECTOR,
which extracts the x coordinate;
posny
, also a selector, which extracts the y coordinate.
In general, the names of these new operations are created by prefixing the name of the structure with ``make'' and by postfixing the name with all the field names. This naming convention appears to be complicated but, with some practice, it is easy to remember.
Now consider the following example:
(definestruct entry (name zip phone))
The structure represents a simplified entry into an address book. Each
entry
combines three values. We also say that each entry
structure has three fields: name
, zip
, and
phone
. Because there are three fields, the constructor
makeentry
consumes three values. For example,
(makeentry 'PeterLee 15270 '6067771)
creates an entry
structure with 'PeterLee
in the
name
field, 15270
in the zip
field, and
'6067771
in the phone
field.
One way to think of a structure is as a box with as many compartments as there are fields:
'PeterLee 15270 '6067771

entry
structures.
The definestruct
definition of entry
also introduces new
selectors:
entryname entryzip entryphone
Here is how we can use the first one:
(entryname (makeentry 'PeterLee 15270 '6067771)) = 'PeterLee
If we give the structure a name,
(define phonebook (makeentry 'PeterLee 15270 '6067771))
then we can use the selectors in the Interactions window to extract the data from the three fields:
(entryname phonebook) = 'PeterLee (entryzip phonebook) = 15270 (entryphone phonebook) = '6067771
Put more graphically, a constructor creates a box with several compartments and puts values in it. A selector reveals the contents of a particular compartment, but leaves the box alone.
Here is one final example, a structure for representing rock stars:
(definestruct star (last first instrument sales))
It defines the class of star
structures, each of which has four
fields. Accordingly, we get five new primitive operations:
makestar starlast starfirst starinstrument starsales
The first is for constructing star
structures; the others are
selector operations for extracting values from a star
structure.
To create a star
structure, we apply makestar
to three
symbols and a positive integer:
(makestar 'Friedman 'Dan 'ukelele 19004) (makestar 'Talcott 'Carolyn 'banjo 80000) (makestar 'Harper 'Robert 'bagpipe 27860)
To select the first name of a star structure called E
, we use
(starfirst E)
Other fields are extracted with other selectors.
Exercise 6.3.1. Consider the following structure definitions:
(definestruct movie (title producer))
(definestruct boyfriend (name hair eyes phone))
(definestruct cheerleader (name number))
(definestruct CD (artist title price))
(definestruct sweater (material size producer))
What are the names of the constructors and the selectors that each of them adds to Scheme? Draw box representations for each of these structures. Solution
Exercise 6.3.2. Consider the following structure definition
(definestruct movie (title producer))
and evaluate the following expressions:
(movietitle (makemovie 'ThePhantomMenace 'Lucas))
(movieproducer (makemovie 'TheEmpireStrikesBack 'Lucas))
Now evaluate the following expressions, assuming x
and y
stand for arbitrary symbols:
(movietitle (makemovie x y))
(movieproducer (makemovie x y))
Formulate equations that state general laws concerning the relationships of
movietitle
and movieproducer
and
makemovie
.
Solution
Functions both consume and produce structures. Suppose we need to record an
increase of sales for one of our stars. This act should be recorded in the
star's record. To do so, we should have a function that consumes a
star
structure and produces a star
structure with the
same information except for the sales component. Let's assume for now that
the function adds 20000 to the star's sales.
First, we write down a basic description of the function, using our contract, header, and purpose format:
;;incrementsales : star > star
;; to produce astar
record likeastar
with20000
more sales (define (incrementsales astar) ...)
Here is an example of how the function should process star
structures:
(incrementsales (makestar 'Abba 'John 'vocals 12200)) should produce (makestar 'Abba 'John 'vocals 32200))
The three sample star
structures from above are also good
examples of potential inputs.
The incrementsales
function must construct a new star
structure with makestar
, but to do so, it must also extract the
data in astar
. After all, almost all of the data in
astar
is a part of the star
structure produced by
incrementsales
. This suggests that the definition of
incrementsales
contains expressions that extract the four
fields of astar
:
(define (incrementsales astar) ... (starlast astar) ... ... (starfirst astar) ... ... (starinstrument astar) ... ... (starsales astar) ... )
As we have seen with the examples, the function adds 20000
to
(starsales astar)
and assembles the four pieces of data into a
star
structure with
makestar
. Figure 9 contains the complete
definition.
Exercise 6.3.3.
Provide a structure definition that represents an airforce's jet fighters.
Assume that a fighter has four essential properties: designation
('f22
, 'tornado
, or 'mig22
), acceleration,
topspeed, and range. Then develop the function withinrange
. The
function consumes a fighter record and the distance of a target from the
(fighter's) base. It determines whether the fighter can reach the intended
target. Also develop the function reducerange
. The function
consumes a fighter record and produces one in which the range
field is reduced to 80% of the original value.
Solution
Consider the following expression:
(makeposn 'Albert 'Meyer)
It constructs a posn
structure from two symbols. If we now apply
distanceto0
to this structure, the computation fails miserably:
(distanceto0 (makeposn 'Albert 'Meyer)) = (sqrt (+ (sqr (posnx (makeposn 'Albert 'Meyer))) (sqr (posny (makeposn 'Albert 'Meyer))))) = (sqrt (+ (sqr 'Albert) (sqr (posny (makeposn 'Albert 'Meyer))))) = (sqrt (+ (* 'Albert 'Albert) (sqr (posny (makeposn 'Albert 'Meyer)))))
That is, it requires us to multiply 'Albert
with itself. Similarly,
(makestar 'Albert 'Meyer 10000 'electricorgan)
does not produce a star
structure according to our intentions. In
particular, the structure is not suitable for processing by
incrementsales
.
To avoid such problems and to assist with the development of functions, we must add a data definition to each structure definition.
Data Definitions 
A DATA DEFINITION
states, in a mixture of English and Scheme, how we intend to use
a class of structures and how we construct elements of this class of
data. For example, here is a data definition for posn
structures:
A posn is a structure:
(makeposn x y)
x
and y
are numbers.
It says that a valid posn
structure always contains two
numbers, and nothing else. Hence, when we use makeposn
to create
a posn
structure, we must apply it to two numbers; when a function
contains selector expressions for posn
structures, we may now
assume that their result is a number.
The data definition for star
structures is only slightly more
complicated:
(makestar last first instrument sales)
last
, first
, and instrument
are symbols
and sales
is a number.
This data definition says that valid star
structures
contain symbols in the fields for last
name, first
name,
and instrument
, and a number in the sales
field.

In general, a data definition identifies a subclass of Scheme's universe of
values: see figure 10. As we have seen so far, Scheme's
universe contains numbers, symbols, images, strings, chars, booleans, and
many different classes of structures. Our functions, however, are intended
to work only for a subclass of values. For example, areaofdisk
consumes only numbers; reply
from section 5 consumes
only symbols. A few subclasses, such as number
, already have
names, because they are useful for all kinds of programming tasks. Others
are only interesting in the context of a specific problem. For those
cases, a programmer should introduce a data definition.
The most important role of a data definition is that of a covenant between
programmers and users. We expect both groups to respect such data
definitions, and we expect the programmer to exploit it for the function
construction. For example, when the programmer of distanceto0
specifies that all posn
s contain two numbers, a user must always
apply distanceto0
to a posn
structure with two
numbers. Furthermore, as we will discuss over the next few sections, we
expect a programmer to exploit data definitions for function
developments. Naturally, a data definition in English and Scheme does not
prevent us from abusing makeposn
. It is, however, a written
statement of intent, and a person who willingly violates or ignores this
covenant must face the consequences of illbehaving
computations.^{20}
Exercise 6.4.1. Provide data definitions for the following structure definitions:
(definestruct movie (title producer))
(definestruct boyfriend (name hair eyes phone))
(definestruct cheerleader (name number))
(definestruct CD (artist title price))
(definestruct sweater (material size producer))
Make appropriate assumptions about what data goes with which field. Solution
Exercise 6.4.2. Provide a structure definition and a data definition for representing points in time since midnight. A point in time consists of three numbers: hours, minutes, and seconds. Solution
Exercise 6.4.3.
Provide a structure definition and a data definition for representing
threeletter word
s. A word consists of letters, which we
represent with the symbols 'a
through
'z
.
Solution
Sections 6.1 through 6.4 suggest that the design of functions for compound data proceeds in a regular manner. First, a programmer must recognize that structures are needed. We follow the simple rule of using structures whenever the description of some object specifies several pieces of information. If we don't use structures in these cases, we quickly lose track of which data belongs to which object, especially when we write large functions that process massive amounts of data.
Second, a programmer can use the structure and data definitions for the organization of a function. We use the term template when we design functions. As we will see in this and many future sections, the template matches the data definition, and the template is the essential step in the careful design of functions.
To emphasize this point, we modify our function design recipe from section 2.5 to accommodate compound data. Most importantly, working with compound data requires adjustments in a few of the basic design steps and two new steps: data analysis and template design:

Until now we could use Scheme's classes of atomic data (numbers, symbols, images, etc.) to represent information. But they are not enough. If we discover that an object has N properties, we introduce a structure definition with N fields and supply a data definition that specifies what kind of data the fields may contain.
Let us consider functions that process student records at a school. If a student's interesting properties for a school are
the first name,
the last name, and
the name of the homeroom teacher,
then we should represent information about a student as a structure:
(definestruct student (last first teacher))
Here is the data definition that specifies the class of student structures as precisely as possible:
(makestudent l f t)
l
, f
, and t
are symbols.The corresponding data class contains structures like these:
(makestudent 'findler 'kathi 'matthias) (makestudent 'fisler 'sean 'matthias) (makestudent 'flatt 'shriram 'matthias)
number
and symbol
,
and those names that we introduced in data definitions, such as
student
.
In other words, a template expresses what we know about the inputs, and nothing about the outputs. We can therefore use the same template for all functions that consume the same kind of structure. Also, because a template does not express anything about the purpose of the function, we can formulate it before or after we have developed examples.
Consider a function that consumes a student
structure and a teacher
name:
;; processstudent : student symbol > ???
(define (processstudent astudent ateacher) ...)
Then astudent
is a parameter that stands for a structure and
ateacher
stands for just a symbol. The template therefore has the
following shape:
;; processstudent : student symbol > ???
(define (processstudent astudent ateacher)
... (studentlast astudent) ...
... (studentfirst astudent) ...
... (studentteacher astudent) ...)
The ???
output reminds us that we don't assume anything about the
output of the function. We design every function that consumes a
student
structure using this template.
student
structures. The first function, check
, is supposed
to return the last name of the student if the teacher's name is equal to
ateacher
and 'none
otherwise:
(check (makestudent 'Wilson 'Fritz 'Harper) 'Harper) ;; expected value: 'Wilson (check (makestudent 'Wilson 'Fritz 'Lee) 'Harper) ;; expected value 'none
The second function, transfer
, is supposed to produce a student
structure that contains the same information as astudent
except
for the teacher field, which should be ateacher
:
(transfer (makestudent 'Wilson 'Fritz 'Harper) 'Lee) ;; expected value: (makestudent 'Wilson 'Fritz 'Lee) (transfer (makestudent 'Woops 'Helen 'Flatt) 'Fisler) ;; expected value: (makestudent 'Woops 'Helen 'Fisler)
Let us return to our first example, check
:
(define (check astudent ateacher) (cond [(symbol=? (studentteacher astudent) ateacher) (studentlast astudent)] [else 'none]))
This particular function uses two of the three selector expressions from the
template. Specifically, it compares the result of the selector expression
(studentteacher astudent)
with ateacher
and, if they
are equal, produces the result of (studentlast astudent)
. Just
naming the results of the selector expressions and reading the problem
statement makes the definition obvious.
Similarly, the transfer
function is easy to define using the
template and the examples:
(define (transfer astudent ateacher) (makestudent (studentlast astudent) (studentfirst astudent) ateacher))
This second function uses the same two selector expressions as the first example, but in a different way. The key observation, however, is that the template reminds us of all the information that we have available. When we define the function, we must use and combine the available information.
Figure 12 presents the recipe for compound data in tabular form. In practice, though, a function contains many functions that all work on the same class of input data. It is therefore normal to reuse the template many times, which means that examples are often constructed after the template is set up. Compare it with the design recipes in figures 4 and 6.

Exercise 6.5.1. Develop templates for functions that consume the following structures:
(definestruct movie (title producer))
(definestruct boyfriend (name hair eyes phone))
(definestruct cheerleader (name number))
(definestruct CD (artist title price))
(definestruct sweater (material size producer))
.
Solution
Exercise 6.5.2.
Develop the function time>seconds
, which consumes a time
structure (see exercise 6.4.2) and produces the number of seconds
since midnight that the time
structure represents.
Example:
(time>seconds (maketime 12 30 2)) ;; expected value: 45002
Explain the example. Solution
Use draw.ss 
Implementing a computer game often requires moving a picture across a computer monitor. In figure 13, for example, a simplistic face is moved from the left part of the canvas toward the right border. For simplicity, our pictures consist of many colored circles and rectangles. From section 6.2, we already know, for example, how to draw and erase a circle. Here we learn to translate a circle, that is, to move its representation along some line. In sections 7.4, 10.3, and 21.4 we learn to move entire pictures with compact programs.^{21}

Following the design recipe, we start with structure and data definitions, then move on to templates, and finally write the necessary functions. The first sequence of exercises covers circles; the second one is about rectangles.
A First Note on Iterative Refinement: This method of developing large programs is our first taste of ITERATIVE REFINEMENT. The basic idea behind iterative refinement is to start with a simple version of the program, that is, a version that deals with the most important part of the problem. In this section, we start with functions that move the most basic shapes: circles and rectangles. Then we refine the program to deal with more and more complex situations. For example, in section 10.3 we learn to deal with pictures that consist of an arbitrary number of circles and rectangles. Once we have a complete program, we edit it so that others can easily read and modify it, too. Section 21.4 covers this aspect of the example.
Refining a program in this manner is the most prevalent method of designing complex programs. Of course, we must know the eventual goal for this method to succeed, and we must always keep it in mind. It is therefore a good idea to write down an action plan, and to reconsider the plan after each refinement step. We will discuss this process again in section 16.
Exercise 6.6.1.
Provide a structure definition and a data definition for representing
colored circles. A circle
is characterized by three pieces of
information: its center, its radius, and the color of its perimeter. The
first is a posn
structure, the second a number, and the third a
(color) symbol.
Develop the template funforcircle
, which outlines a function
that consumes circle
s. Its result is
undetermined.
Solution
Exercise 6.6.2.
Use funforcircle
to develop drawacircle
. The function
consumes a circle
structure and draws the corresponding circle on
the screen. Use (start 300 300)
to create the canvas before
testing the function.
Solution
Exercise 6.6.3.
Use the template funforcircle
to develop
incircle?
. The function consumes a circle
structure and
a posn
and determines whether or not the pixel is inside the
circle. All pixels whose distance to the center is less or equal to the
radius are inside the circle; the others are outside.
Consider the circle in figure 14. The circle's center is
(makeposn 6 2)
, its radius is 1
. The pixel labeled
A
, located at (makeposn 6 1.5)
, is inside the
circle. The pixel labeled B
, located at (makeposn 8 6)
,
is outside.
Solution
Exercise 6.6.4.
Use the template funforcircle
to develop
translatecircle
. The function consumes a circle
structure and a number delta
. The result is a circle
whose center is delta
pixels to the right of the input.
The function has no effect on the canvas.
Geometric Translation: Moving a geometric shape along a straight line is referred to as a translation. Solution
Exercise 6.6.5.
Use the template funforcircle
to develop
clearacircle
. The function consumes a circle
structure
and clears the corresponding circle on the
canvas.
Solution
Exercise 6.6.6.
Define the function drawandclearcircle
, which draws a circle
structure, waits for a short time, and clears it. To implement a waiting
period, the teachpack draw.ss provides the function
sleepforawhile
. It consumes a number and puts the program to
sleep for that many seconds; its result is true
. For example,
(sleepforawhile 1)
waits for one second.
Solution
The following function is the key ingredient for moving a circle across a canvas, one step at a time:
;;movecircle : number circle > circle
;; to draw and clear a circle, translate it bydelta
pixels (define (movecircle delta acircle) (cond [(drawandclearcircle acircle) (translatecircle acircle delta)] [else acircle]))
It draws and clears the circle on the canvas and then produces the new
circle
structure so that another drawandclear effect
displays the circle at a new position:
(start 200 100) (drawacircle (movecircle 10 (movecircle 10 (movecircle 10 (movecircle 10 ... a circle ...)))))
This expression moves the circle four times, by 10 pixels each, and also
shows this movement on the canvas. The last drawacircle
is
necessary because we wouldn't otherwise see the last move on the screen.
Exercise 6.6.7.
Provide a structure definition and a data definition for representing
colored rectangles. A rectangle
is characterized by four
pieces of information: its upperleft corner, its width, its height, and its
fill color. The first is a posn
structure, the second and third
quantities are plain numbers, and the last one is a color.
Develop the template funforrect
, which outlines a function that
consumes rectangle
s. Its result is
undetermined.
Solution
Exercise 6.6.8.
Use the template funforrect
to develop
drawarectangle
. The function consumes a rectangle
structure and draws the corresponding rectangle on the screen. In contrast
to circles, the entire rectangle is painted in the matching color. Remember
to use (start 300 300)
to create the canvas before testing the
function.
Solution
Exercise 6.6.9.
Use the template funforrect
to develop inrectangle?
. The
function consumes a rectangle
structure and a posn
and
determines whether or not the pixel is inside the rectangle. A pixel is within a
rectangle if its horizontal and vertical distances to the upperleft corner are
positive and smaller than the width and height of the rectangle,
respectively.
Consider the rectangle in figure 14. This rectangle's key
parameters are (makeposn 2 3)
, 3
, and 2
. The
pixel labeled C
is inside of the rectangle, B
is
outside.
Solution
Exercise 6.6.10.
Use the template funforrect
to develop
translaterectangle
. The function consumes a rectangle
structure and a number delta
. The result is a rectangle
whose upperleft corner is delta
pixels to the right of the
input. The function has no effect on the
canvas.
Solution
Exercise 6.6.11.
Use the template funforrect
to develop
cleararectangle
. It consumes a rectangle
structure and
clears the corresponding rectangle on the canvas.
Solution
Exercise 6.6.12.
Here is the moverectangle
function:
;;moverectangle : number rectangle > rectangle
;; to draw and clear a rectangle, translate it bydelta
pixels (define (moverectangle delta arectangle) (cond [(drawandclearrectangle arectangle) (translaterectangle arectangle delta)] [else arectangle]))
It draws and clears a rectangle circle on the canvas and then produces a translated version.
Develop drawandclearrectangle
, which draws a rectangle, sleeps
for a while, and then clears the rectangle. Finally, create a rectangle
and use the functions of this exercise set to move it four
times.
Solution
Use draw.ss, hangman.ss 

Hangman is a twoplayer, wordguessing game. One player thinks of a threeletter^{22} word and draws the noose of a gallows (see figure 15); the other player tries to guess the word, one letter at a time. For every wrong guess, the first player adds another part to the drawing (see figure 15): first the head, then the body, the arms, and the legs. If, however, a guess agrees with one or two letters in the chosen word, the first player reveals the position(s) where this letter occurs. The game is over when the second player guesses the complete word or when the first player has completed the stick figure.
Let's design a program that plays the role of the first player. The program consists of two parts: one for drawing the figure, and another for determining whether a guess occurs in the chosen word and where.
Exercise 6.7.1.
Develop the function drawnextpart
, which draws the pieces of a
hangman figure. The function consumes one of the seven symbols:
'rightleg 'leftleg 'leftarm 'rightarm 'body 'head 'noose 
true
and draws the matching part of the figure.
See figure 15 for three snapshots of intermediate
stages.^{23}
Hints: Add (start 200 200)
to the top of the definition window.
Start with the noose and develop one component at a time. If a component
of the stick figure requires more than one drawing operation, combine the
operations using an andexpression,
which evaluates the two expressions and
ensure that both results are true
.
Solution
The second task of the first player is to determine whether a guess is
among the letters of the chosen word and, if so, where it occurs. Our
recipe requires that, before we design a function for this task, we need to
analyze our data and provide data definitions. The key objects of the
game are words and letters. A word
consists of three letters. A
letter
is represented with the symbols 'a
through
'z
. Using just those letters, however, is not enough because the
program also needs to maintain a word that records how much the second
player has guessed. The solution is to add one extra ``letter'' to our
alphabet that is distinct from the others; the hangman teachpack uses
'_
for this purpose.
Exercise 6.7.2. Provide a structure definition and a data definition for representing threeletter words. Solution
Exercise 6.7.3.
Develop the function reveal
. It consumes three arguments:
the chosen word, which is the word that we have to guess;
the status word, which shows which portion of the word has been revealed so far; and
The function produces a new status word, that is, a word that contains
ordinary letters and '_
. The fields in the new status word are
determined by comparing the guess with each pair of letters from the status
word and the chosen word:
If the guess is equal to the letter in the chosen word, the guess is the corresponding letter in the new status word.
Otherwise, the new letter is the corresponding letter from the status word.
Test the function with the following examples:
(reveal (makeword 't 'e 'a) (makeword '_ 'e '_) 'u) ;; expected value (makeword '_ 'e '_) (reveal (makeword 'a 'l 'e) (makeword 'a '_ '_) 'e) ;; expected value: (makeword 'a '_ 'e) (reveal (makeword 'a 'l 'l) (makeword '_ '_ '_) 'l) ;; expected value (makeword '_ 'l 'l)
The first one shows what happens when the guess
does not occur in
the word; the second one shows what happens when it does occur; and the
last one shows what happens when it occurs twice.
Hints: (1) Remember to develop auxiliary functions when a definition becomes too large or too complex to manage.
(2) The function reveal
consumes two structures and one atomic
value (a letter). This suggests that we use the design recipe for compound
data (figure 12). For the template, it is best to write down
the selector expressions in a twocolumn format, one column per
word.
Solution
When the functions drawnextpart
and reveal
are properly
tested, set teachpack to hangman.ss and play the game by evaluating
(hangman makeword reveal drawnextpart)
The hangman
function chooses a threeletter word randomly and
displays a window with a popup menu for letters. Choose letters and, when
ready, click the Check button to see whether the guess is correct.
Comment out the test cases for exercise 6.7.1 so that their
drawing effects don't interfere with those of hangman
.
^{18} An alternative terminology is ``to access the fields of a record.'' We prefer to think of structure values as containers from which we can extract other values.
^{19} For more documentation, see DrScheme's Help Desk.
^{20} DrScheme provides an optional tool that permits programmers to check whether users and programmers respect the data definition for a particular structure. To do so, a programmer must state data definitions in a special language. Although checking the adherence to data definitions is important for large programs, an introductory course can avoid this topic.
^{21} This series of sections was inspired by Ms. Karen Buras and her son.
^{22} In reality, we would want to play the game with words of arbitrary length, but a game based on threeletter words is easier to implement for now. We return to the problem in exercise 17.6.2.
^{23} Thanks to Mr. John Clements for the artistic version of drawnextpart.