- <para>
- As you've seen, we often build data structures for a particular kind
- of data. For example, in implementing turtle graphics, we might begin
- by storing four pieces of information on each turtle. (There are other
- useful pieces of information, but these are four that can get us started.)
- </para>
- <itemizedlist>
- <listitem>
- 0: the image on which the turtle draws;
- </listitem>
- <listitem>
- 1: a real number for the x coordinate of the position of the turtle;
- </listitem>
- <listitem>
- 2: a real number for the y coordinate of the position of the turtle; and
- </listitem>
- <listitem>
- 3: a real number for the angle of the directions in which the turtle
- is facing.
- </listitem>
- </itemizedlist>
- <para>
- We then choose whether we want to store those attributes in a list
- or a vector. Suppose we store those components in a vector, with the
- image at position 0, the x coordinate at position 1, the
- y coordinate at position 2, and the angle at position 3.
- </para>
- <para>
- Once we've designed a representation, we could then tell other programmers
- about this representation, and let them rely on the structure (e.g.,
- someone who wants to change the angle of a turtle would do a
- <code>vector-set!</code> at index 3).
- </para>
- <para>
- However, suppose we change the representation (e.g., we design a
- position type and decide to use that type to represent the position of
- the turtle). In that case other programmers must then change their
- code to match the new representation. Hence, it is often better to
- provide a set of procedures to give other programmers access to the
- key components of our structure. If they use only our procedures,
- then we can change the representation freely (as long as we change
- our procedures correspondingly) and their code will continue to work.
- </para>
- <para>
- Here are some sample procedures for this simple type of turtle.
- </para>
- <programlisting>
- (define make-turtle
- (lambda (image)
- (cond
- ((not (image? image))
- (error "make-turtle: parameter 0 (image) must be an image"))
- (else
- (vector image 0 0 0)))))
- (define turtle-get-image
- (lambda (turtle)
- (vector-ref turtle 0)))
- (define turtle-get-x
- (lambda (turtle)
- (vector-ref turtle 1)))
- (define turtle-get-y
- (lambda (turtle)
- (vector-ref turtle 2)))
- (define turtle-get-angle
- (lambda (turtle)
- (vector-ref turtle 3)))
- (define turtle-set-angle
- </programlisting>
- ...
- (define turtle-set-angle!
- (lambda (turtle new-angle)
- (vector-set! turtle 3 new-angle)))
- (define turtle-turn!
- (lambda (turtle angle)
- (vector-set! turtle 3 (+ (vector-ref turtle 3) angle))))
- (define turtle-forward!
- (let ((degrees-to-radians (/ pi 180)))
- (lambda (turtle distance)
- (let* ((image (vector-ref turtle 0))
- (x (vector-ref turtle 1))
- (y (vector-ref turtle 2))
- (angle (vector-ref turtle 3))
- (newx (+ x (cos angle)))
- (newy (+ y (sin angle))))
- (image-draw-line! image x y newx newy)
- (vector-set! turtle 1 newx)
- (vector-set! turtle 2 newy)))