Structure and Interpretation of Computer Programs



Yüklə 2,71 Mb.
Pdf görüntüsü
səhifə47/222
tarix08.08.2018
ölçüsü2,71 Mb.
#61085
1   ...   43   44   45   46   47   48   49   50   ...   222

Higher-order operations

In addition to abstracting patterns of combining painters, we can work at a higher level, abstracting

patterns of combining painter operations. That is, we can view the painter operations as elements to

manipulate and can write means of combination for these elements -- procedures that take painter

operations as arguments and create new painter operations.

For example, 

flipped-pairs

 and 


square-limit

 each arrange four copies of a painter’s image

in a square pattern; they differ only in how they orient the copies. One way to abstract this pattern of

painter combination is with the following procedure, which takes four one-argument painter operations

and produces a painter operation that transforms a given painter with those four operations and

arranges the results in a square. 

Tl



tr



bl

, and 



br

 are the transformations to apply to the top left

copy, the top right copy, the bottom left copy, and the bottom right copy, respectively.

(define (square-of-four tl tr bl br)

  (lambda (painter)

    (let ((top (beside (tl painter) (tr painter)))

          (bottom (beside (bl painter) (br painter))))

      (below bottom top))))

Then 

flipped-pairs



 can be defined in terms of 

square-of-four

 as follows:

24

(define (flipped-pairs painter)



  (let ((combine4 (square-of-four identity flip-vert

                                  identity flip-vert)))

    (combine4 painter)))

and 


square-limit

 can be expressed as

25

(define (square-limit painter n)



  (let ((combine4 (square-of-four flip-horiz identity

                                  rotate180 flip-vert)))

    (combine4 (corner-split painter n))))

Exercise 2.45.  

Right-split

 and 

up-split


 can be expressed as instances of a general splitting

operation. Define a procedure 

split

 with the property that evaluating 



(define right-split (split beside below))

(define up-split (split below beside))

produces procedures 

right-split

 and 

up-split


 with the same behaviors as the ones already

defined. 



Frames

Before we can show how to implement painters and their means of combination, we must first

consider frames. A frame can be described by three vectors -- an origin vector and two edge vectors.

The origin vector specifies the offset of the frame’s origin from some absolute origin in the plane, and

the edge vectors specify the offsets of the frame’s corners from its origin. If the edges are

perpendicular, the frame will be rectangular. Otherwise the frame will be a more general 

parallelogram.



Figure 2.15 shows a frame and its associated vectors. In accordance with data abstraction, we need not

be specific yet about how frames are represented, other than to say that there is a constructor 

make-frame

, which takes three vectors and produces a frame, and three corresponding selectors 

origin-frame

edge1-frame



, and 

edge2-frame

 (see exercise 2.47).

Figure 2.15:  A frame is described by three vectors -- an origin and two edges.

Figure 2.15:  A frame is described by three vectors -- an origin and two edges.

We will use coordinates in the unit square (0< x,y< 1) to specify images. With each frame, we

associate a frame coordinate map, which will be used to shift and scale images to fit the frame. The

map transforms the unit square into the frame by mapping the vector v = (x,y) to the vector sum 

For example, (0,0) is mapped to the origin of the frame, (1,1) to the vertex diagonally opposite the

origin, and (0.5,0.5) to the center of the frame. We can create a frame’s coordinate map with the

following procedure:

26

(define (frame-coord-map frame)



  (lambda (v)

    (add-vect

     (origin-frame frame)

     (add-vect (scale-vect (xcor-vect v)

                           (edge1-frame frame))

               (scale-vect (ycor-vect v)

                           (edge2-frame frame))))))

Observe that applying 

frame-coord-map

 to a frame returns a procedure that, given a vector,

returns a vector. If the argument vector is in the unit square, the result vector will be in the frame. For

example, 

((frame-coord-map a-frame) (make-vect 0 0))



returns the same vector as 

(origin-frame a-frame)



Exercise 2.46.  A two-dimensional vector v running from the origin to a point can be represented as a

pair consisting of an x-coordinate and a y-coordinate. Implement a data abstraction for vectors by

giving a constructor 

make-vect

 and corresponding selectors 

xcor-vect

 and 

ycor-vect



. In

terms of your selectors and constructor, implement procedures 

add-vect

sub-vect



, and 

scale-vect

 that perform the operations vector addition, vector subtraction, and multiplying a

vector by a scalar: 



Exercise 2.47.  Here are two possible constructors for frames: 

(define (make-frame origin edge1 edge2)

  (list origin edge1 edge2))

(define (make-frame origin edge1 edge2)

  (cons origin (cons edge1 edge2)))

For each constructor supply the appropriate selectors to produce an implementation for frames. 



Painters

A painter is represented as a procedure that, given a frame as argument, draws a particular image

shifted and scaled to fit the frame. That is to say, if 

p

 is a painter and 



f

 is a frame, then we produce 

p

’s

image in 



f

 by calling 

p

 with 


f

 as argument.

The details of how primitive painters are implemented depend on the particular characteristics of the

graphics system and the type of image to be drawn. For instance, suppose we have a procedure 

draw-line

 that draws a line on the screen between two specified points. Then we can create

painters for line drawings, such as the 

wave


 painter in figure 2.10, from lists of line segments as 

follows:


27

(define (segments->painter segment-list)

  (lambda (frame)

    (for-each

     (lambda (segment)

       (draw-line

        ((frame-coord-map frame) (start-segment segment))

        ((frame-coord-map frame) (end-segment segment))))

     segment-list)))

The segments are given using coordinates with respect to the unit square. For each segment in the list,

the painter transforms the segment endpoints with the frame coordinate map and draws a line between

the transformed points.




Yüklə 2,71 Mb.

Dostları ilə paylaş:
1   ...   43   44   45   46   47   48   49   50   ...   222




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©genderi.org 2024
rəhbərliyinə müraciət

    Ana səhifə