Skip to main content

Laboratory: Anonymous Procedures

Summary: In this laboratory, you will explore the use of a variety of forms of anonymous procedures. Our primary focus will be on the use of anonymous procedures and the “drawings as values” model to visualize a variety of functions (the mathematical kind).

Preparation

Make a copy of anonymous-procedures-lab.rkt, which contains some useful code for this lab.

Exercises

Exercise 1: Our Starting Point(s)

In the code for this lab, there is a value named points.

a. Explain what that value contains.

b. Check your answer experimentally by rendering that value.

> (check-drawings points)

Exercise 2: Basic Visualization

In this laboratory, we’re going to explore ways to visualize functions by systematically shifting the values in points. Hence, most of our commands will look something like:

> (check-drawings (map vshift-drawing
                       (map function numbers)
                       points))

Use this form to visualize the functions increment, sqrt, and square. You should visualize the three functions separately.

You may notice that the function is “upside-down”, because the GIMP coordinate system is opposite the Cartesian coordinate system. We won’t worry about this switch in orientation.

Exercise 3: Anonymous Procedures

Here’s our traditional definition of a function that multiplies its parameter by 5. (We’ve included a bit more documentation than normal.)

;;; Procedure:
;;;   times5
;;; Parameters:
;;;   x, a number
;;; Purpose:
;;;   Multiply x by 5
;;; Produces:
;;;   result, a number
;;; Preconditions:
;;;   If x is an inexact number, it is no more than one-fifth the highest
;;;     inexact number and no less than one-fifth the highest inexact
;;;     number.
;;; Postconditions:
;;;   result = 5*x, to within machine precision.
;;;   result is the same "type" as x.  For example,
;;;     If x is exact, result is exact.
;;;     If x is inexact, result is inexact.
;;;     If x is an integer, result is an integer.
;;;     If x is complex, result is complex.
(define times5 
  (lambda (x) 
    (* 5 x)))

a. Using the form from the previous exercise, visualize this function.

b. As we noted in the reading, instead of writing times5 for the function, we can write a lambda expression. Fill in the rest of the following to get the same effect as we got in the previous step.

> (check-drawings (map vshift-drawing 
                       (map (lambda (x) ______) numbers)
                       points))

c. Write a similar expression to visualize the function “multiply x by -3”.

d. Write a similar expression to visualize the function “subtract ten from x”.

e. Write a similar expression to visualize the remainder you get when dividing x by 10.

After completing this exercise, you may want to compare your answers to those in the notes.

Exercise 4: Sectioning

These lambda expressions are a bit long. As you may recall from the reading we can also create simple procedures with left-section (l-s) and right-section (r-s).

a. Predict the results of the following expressions.

> (map (l-s + 10) (iota 20))
> (map (r-s + 10) (iota 20))
> (map (l-s - 10) (iota 20))
> (map (r-s - 10) (iota 20))
> (map (l-s * 10) (iota 20))
> (map (r-s * 10) (iota 20))
> (map (l-s / 10) (iota 20))
> (map (r-s / 10) (iota 20))
> (map (r-s modulo 10) (iota 20))

b. Check your answers experimentally. If any of the results fail to make sense, please discuss them. (You might talk to a classmate, the class mentor, your teacher, or some combination thereof.)

c. Redo parts b, c, d, and e from the previous exercise using sections instead of the lambda expressions. If you have difficulty, you may want to check the notes on this exercise.

d. Go back to the definition of points and write an expression to space them out a bit horizontally, multiplying the values in numbers by 3 before shifting.

Exercise 5: Composition

In each of these cases, we’ve graphed a fairly simple function. What if we want to do something a bit more complex. For example, what if, after computing the square root, we want to “stretch out” the visualization by multiplying by 5? What if we want to first subtract 25 (putting the origin closer to the middle of the screen) and then multiply by 5? What if we want to do some other weird combination of procedures?

The compose procedure, described in the reading, helps with all of these problems and more. As you may recall, (compose f g) is a function that applies g and then applies f.

a. Predict and check the results of the following expressions. You may want to check your prediction for each one before going on to the next.

> (map (compose increment square) (iota 20))
> (map (compose square increment) (iota 20))
> (map (compose increment (l-s * 2)) (iota 20))
> (map (compose (l-s * 2) increment) (iota 20))
> (map (compose (l-s + 10) (l-s * 2)) (iota 20))
> (map (compose (l-s * 2) (r-s modulo 5)) (iota 20))

b. The square root visualiation is somewhat shallow. Let’s stretch it out a bit. Write an expression to visualize the function “compute the square root and then multiply by 10”.

c. In contrast, the visualization of the square function is perhaps stretched out too much. Write an expression to visualize the function “square and then divide by 100”.

d. Write an expression to visualize the function “compute the remainder after dividing by 11, and then multiply that remainder by 7”.

e. Write an expression to visualize the function “multiply by five and then compute the remainder after dividing by 11”.

f. Write an expression to visualize the function “divide by 10, compute the sine (with sin), and then multiply the result by 100”.

For Those with Extra Time

If you find that you have extra time, you can try one of these extra problems or the explorations below.

Extra 1: Implement Sectioning

Implement your own versions of left-section and right-section. You’ll probably need new names for them, such as my-left-section.

Extra 2: Implement Composition

Implement your own version of compose. You’ll probably need a new name, such as my-compose.

Extra 3: Making Constant Functions

Write a function, (constant n), that returns a function that takes any value as input and returns n.

> (define five (constant 5))
> (five 1)
5
> (five "hello")
5
> (five five)
5

Explorations

If you happen to finish early, experiment with various compositions and sections of functions. For example, you might try to get a “stairstep” graph by dividing and then rounding.

Here’s a simple framework. Anywhere you see underscores, you can plug in a function, such as (compose (r-s mod 256) (r-s * 20)) or (lambda (x) (+ 3 (* x 2))).

(define num-points 50)

(define numbers (iota num-points))

(define make-color
  (lambda (n)
    (irgb (___ n) (___ n) (___ n))))

(define basic-drawing
  (drawing-group drawing-unit-circle
                 (vshift-drawing 0.5 drawing-unit-square)))

(define my-drawing-01
  (map recolor-drawing
       (map (compose make-color ___) numbers) ; color
       (map hshift-drawing
            (map ___ numbers)       ; hshift
            (map vshift-drawing
                 (map ___ numbers)     ; vshift
                 (map hscale-drawing
                      (map ____ numbers)  ; hscale
                      (map vscale-drawing
                           (map ___ numbers) ; vscale
                           (make-list num-points basic-drawing)))))))

Notes

Notes on Exercise 3

Here are our solutions to the problems.

b.

> (check-drawings (map vshift-drawing
                       (map (lambda (x) (* 5 x)) numbers)
                       points))

c.

> (check-drawings (map vshift-drawing
                       (map (lambda (x) (* -3 x)) numbers)
                       points))

d.

> (check-drawings (map vshift-drawing
                       (map (lambda (x) (- x 10)) numbers)
                       points))

e.

> (check-drawings (map drawing-vshift
                       (map (lambda (x) (remainder x 10)) numbers)
                       points))

Notes on Exercise 4

For part c, we expect something like the following:

> (check-drawings (map vshift-drawing 
                       (map (l-s * 5) numbers)
                       points))
> (check-drawings (map vshift-drawing 
                       (map (l-s - 3) numbers)
                       points))
> (check-drawings (map vshift-drawing 
                       (map (r-s * 10) numbers)
                       points))
> (check-drawings (map vshift-drawing 
                       (map (r-s remainder 10) numbers)
                       points))

For the last of the three, it would also be reasonable to write

> (check-drawings (map vshift-drawing 
                       (map (r-s mod 10) numbers)
                       points))