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 make-posn, which consumes two numbers and makes a posn. For example,
(make-posn 3 4)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.(make-posn 8 6)
(make-posn 5 12)
Now consider a function that computes how far some pixel is from the origin. The contract, header, and purpose statement are easy to formulate:
;; distance-to-0 : posn -> number ;; to compute the distance of a-posn to the origin (define (distance-to-0 a-posn) ...)In other words, distance-to-0 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:
(distance-to-0 (make-posn 0 5)) = 5 ;and (distance-to-0 (make-posn 7 0)) = 7In general, we know from geometry that the distance from the origin to a position with coordinates x and y is distance
Thus,
(distance-to-0 (make-posn 3 4)) = 5(distance-to-0 (make-posn 8 6)) = 10
(distance-to-0 (make-posn 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 distance-to-0 doesn't need to distinguish between different situations. Still, we are stuck now, because distance-to-0 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 make-posn and we don't know how to extract these numbers from a posn structure.
Scheme provides operations for extracting values from
structures.
For posn structures, Scheme
supports two such operations: posn-x and posn-y. The
former operation extracts the x coordinate; the latter extracts the
y coordinate.
To describe how posn-x, posn-y, and make-posn are related, we can use equations that are roughly analogous to the equations that govern addition and subtraction:
(posn-x (make-posn 7 0)) = 7and
(posn-y (make-posn 7 0)) = 0The equations only confirm what we already know. But suppose we introduce the following definition:
(define a-posn (make-posn 7 0))Then we can use the two operations as follows in the Interactions window:
(posn-x a-posn) = 7Naturally, we can nest such expressions:(posn-y a-posn) = 0
(* (posn-x a-posn) 7) = 49(+ (posn-y a-posn) 13) = 13
Now we know enough to complete the definition of distance-to-0. We know that the function's a-posn parameter is a posn structure and that the structure contains two numbers, which we can extract with (posn-x a-posn) and (posn-y a-posn). Let us add this knowledge to our function outline:
(define (distance-to-0 a-posn) ... (posn-x a-posn) ... ... (posn-y a-posn) ...)Using this outline and the examples, the rest is easy:
(define (distance-to-0 a-posn)
(sqrt
(+ (sqr (posn-x a-posn))
(sqr (posn-y a-posn)))))
The function squares (posn-x a-posn) and (posn-y a-posn),
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: