Laboratory: Writing Your Own Procedures


Summary: In this laboratory, you will explore some of the issues that pertain to writing your own procedures.

Preparation

a. Review How Scheme Evaluates Expressions (version 2).

b. Copy the code from the reading into the definitions pane.

Exercises

Exercise 1: Sanity Checks

a. Verify that the four basic values look as they are described in the corresponding reading.

> (image-show (drawing->image black-circle 200 100))
> (image-show (drawing->image purple-ellipse 200 100))
> (image-show (drawing->image blue-i 200 100))
> (image-show (drawing->image red-eye 200 100))

b. Try some of the transformers. For example,

> (image-show (drawing->image (variant-1 black-circle) 200 100))
> (image-show (drawing->image (variant-1 (variant-1 black-circle)) 200 100))
> (image-show (drawing->image (add-right-neighbor red-eye) 200 100))

c. Try the circle constructor.

> (image-show (drawing->image (circle ___ ___ ___) 200 100))

d. Verify that square correctly squares the numbers 5, 10, -3, 1.2, and 0.05.

Exercise 2: Fun with Neighbors

As you may recall, the add-right-neighbor procedure makes a copy of a drawing, places the copy immediately to the right of the original drawing, and combines the two into a new drawing.

a. Write a procedure, (add-smaller-right-neighbor drawing) that combines a drawing with a duplicate neighbor that is 75% of the size of the original drawing.

(add-smaller-right-neighbor red-eye)

b. Write a procedure, add-nearer-right-neighbor drawing) that combines a drawing with a duplicate neighbor of the same size, but that overlaps 20% (so that the left end of the neighbor is 20% left of the right end of the original).

(add-nearer-right-neighbor red-eye)

c. Write a procedure, add-narrow-right-neighbor drawing) that combines a drawing with a duplicate neighbor immediately to the right, with the neighbor the same height, but half the width of the original.

(add-narrow-right-neighbor red-eye)

d. Write a procedure, add-bottom-neighbor drawing) that builds a duplicate neighbor that is immediately below the drawing.

(add-nearer-right-neighbor red-eye)

e. Write a procedure, (add-larger-bottom-neighbor drawing) that builds a 25% larger neighbor that is immediately below the drawing.

Exercise 3: Rendering Drawings

For each of the procedures above, you've likely tested your procedure by applying it to some drawing, rendering that drawing to some image, and then showing the image. For example,

> (image-show (drawing->image (add-bottom-neighbor red-eye) 200 100))

Write a procedure, (check-drawing drawing) that renders the drawing on a 200x100 image and then shows the image. Once we've written that procedure, we can more easily check drawings, as in the following.

> (check-drawing (add-bottom-neighbor red-eye))

Exercise 4: Combining Transformations

We now have procedures that pair an image with a smaller right neighbor and a larger bottom neighbor. What happens if we combine these transformations? For each of the following, predict what the image will look like and then render it to check your prediction.

a. (add-larger-bottom-neighbor (add-smaller-right-neighbor red-eye))

b. (add-smaller-right-neighbor (add-larger-bottom-neighbor red-eye))

c. (add-smaller-right-neighbor (add-nearer-right-neighbor red-eye))

d. (add-smaller-right-neighbor (add-smaller-right-neighbor red-eye))

e. (add-narrow-right-neighbor (add-narrow-right-neighbor red-eye))

f. (add-smaller-right-neighbor (add-narrow-right-neighbor red-eye))

g. (add-narrow-right-neighbor (add-smaller-right-neighbor red-eye))

Exercise 5: Drawing Circles, Revisited

One deficiency of the circle procedure from the reading is that it doesn't allow you to specify the color of the circle.

Rewrite the procedure to take a color as a parameter.

(circle 20 10 10 "blue")

Exercise 6: Drawing Squares

Now that we can draw colored circles using circle, it will be helpful to write procedures that generate other simple shapes. Let's start with squares.

Write a procedure, drawing-of-square that creates a drawing of a square. (We couldn't call this procedure square, because we'd already used that name for the procedure that squares numbers.) You'll note that we have not specified the parameters for this procedure. You should figure them out on your own. (If you have trouble doing so, you can look at the notes on this exercise.)

Exercise 7: Drawing Rectangles

Write a procedure, rectangle that creates a drawing of a rectangle. Once again, you should do your best to figure out appropriate parameters. Here is a sample call, using the parameters we find most natural.

(rectangle 20 10 50 80 "yellow")

If you'd like to know what we thought were appropriate parameters, you can look at the notes on this exercise.

For Those With Extra Time

If you find that you have extra time, you may find it useful to do any of the following exercises. (You need not do them in order.) You may also choose to do one of the explorations.

Extra 1: An Alternate Scaling Mechanism

As you may recall, one potentially confusing aspect of the drawing-scale procedure is that it not only scales the drawing, it also scales the distance of the drawing from the top-left corner.

Write a procedure, (alternate-scale drawing), that scales a drawing, but does not move the drawing. That is, the scaled drawing has the same left edge and the same top edge as the original drawing.

If you're not sure how to approach this problem, you may want to read the notes on this exercise.

Extra 2: Grids of Images

a. Write a procedure, (two-by-two drawing) that creates a compound drawing with four copies of drawing (one shifted right, one shifted down, and one shifted down and right).

b. Write a procedure that takes the result of two-by-two and scales it by 50%, so that the resulting drawing is the same width and height as the original.

c. Using this new procedure, build a four-by-four grid of one of the original images, or one of your own choosing.

Explorations

For each of these explorations, you may find the following drawing an appropriate starting point. You might also start with a house or other drawing you've designed. You might even start with a simple shape.

(define sample
  (drawing-hshift
   (drawing-vshift
    (drawing-group
     (drawing-scale 
      drawing-unit-circle 
      100)
     (drawing-scale 
      (drawing-recolor drawing-unit-circle "yellow") 
      90)
     (drawing-vshift
      (drawing-hscale
       (drawing-vscale 
        drawing-unit-circle
        40)
       60)
      10)
     (drawing-hscale
      (drawing-vscale
       (drawing-recolor drawing-unit-circle "yellow")
       40)
      60)
     (drawing-vshift
      (drawing-group
       (drawing-hshift
        (drawing-group
         (drawing-hscale
          (drawing-vscale
           (drawing-recolor drawing-unit-circle "white")
           15)
          30)
         (drawing-hscale
          (drawing-vscale
           (drawing-recolor drawing-unit-circle "blue")
           15)
          15))
        18)
       (drawing-hshift
        (drawing-group
         (drawing-hscale
          (drawing-vscale
           (drawing-recolor drawing-unit-circle "white")
           15)
          30)
         (drawing-hscale
          (drawing-vscale
           (drawing-recolor drawing-unit-circle "green")
           15)
          15))
        -18))
      -15))
    50)
   50))

Exploration 1: Multiple Neighbors

In Exercise 5, each of the expressions takes one drawing and turn it into four drawings. Explore other ways to use this kind of replication to build an interesting image. (You might also think about ways to create eight, sixteen, or even more copies of the image.)

Exploration 2: More Interesting Neighbors

In the Exercise 4, you developed a number of procedures that pair an image with a neighbor. Create a few variants of those procedures that change the neighbor in an “interesting” way. For example, you might scale it differently horizontally and vertically, you might have it overlap the original figure, you might shift it both horizontally and vertically.

Notes on the Exercises

Notes on Exercise 6: Drawing Squares

We would recommend that your procedure have the form

(define drawing-of-square
  (lambda (left top side-length color)
    ..._))

You might also consider

(define drawing-of-square
  (lambda (side-length left top color)
    ..._))

Return to the exercise.

Notes on Exercise 7: Drawing Rectangles

We would recommend that your procedure have the form

(define rectangle
  (lambda (left top width height color)
    ..._))

Return to the exercise.

Notes on Extra 1: An Alternate Scaling Mechanism

The alternate scaling algorithm is fairly straightforward:

  • Shift the drawing back to the origin. (The top and left should both be 0.)
  • Scale the shifted drawing.
  • Shfit the scaled drawing back to the original place. (The top and left should match the top and left of the original drawing.)

Return to the exercise.

Code from the Reading

; +-----------------+-------------------------------------------------
; | Sample drawings |
; +-----------------+

(define black-circle
  (drawing-hshift
   (drawing-vshift
    (drawing-scale drawing-unit-circle 50)
    40)
    30))

(define purple-ellipse
  (drawing-vshift
   (drawing-hshift
    (drawing-vscale
     (drawing-hscale
      (drawing-recolor drawing-unit-circle "purple")
      50)
     25)
    30)
   10))

(define blue-i
  (drawing-recolor
   (drawing-group
    (drawing-hshift
     (drawing-vshift
      (drawing-scale drawing-unit-circle 8)
      4)
     4)
    (drawing-hshift
     (drawing-vshift
      (drawing-hscale
       (drawing-vscale drawing-unit-square 32)
       8)
      28)
     4))
   "blue"))

(define red-eye
  (drawing-hshift
   (drawing-vshift
    (drawing-group
     (drawing-hscale
      (drawing-vscale
       (drawing-recolor drawing-unit-circle "darkgrey")
       24)
      64)
     (drawing-hscale
      (drawing-vscale
       (drawing-recolor drawing-unit-circle "white")
       20)
      60)
     (drawing-hscale
      (drawing-vscale
       (drawing-recolor drawing-unit-circle "red")
       20)
      16))
    12)
   32))

; +-----------------------------+-------------------------------------
; | Sample drawing transformers |
; +-----------------------------+

(define variant-1
  (lambda (drawing)
    (drawing-hshift
     (drawing-vshift
      (drawing-scale drawing 1.1)
      20)
     15)))

(define variant-pair-1
  (lambda (drawing)
    (drawing-group drawing (variant-1 drawing))))

(define add-right-neighbor
  (lambda (drawing)
    (drawing-group drawing
                   (drawing-hshift drawing
                                   (drawing-width drawing)))))

; +-----------------------------+-------------------------------------
; | Sample drawing constructors |
; +-----------------------------+

(define circle
  (lambda (radius x-center y-center)
    (drawing-hshift
     (drawing-vshift
      (drawing-scale 
       drawing-unit-circle 
       (* 2 radius))
      y-center)
     x-center)))

Return to the exercises


Jerod Weinman