Fundamentals of Computer Science I: Media Computing (CS151.01 2008S)

Laboratory: Naming Values with Local Bindings


Summary: In this laboratory, you will ground your understanding of the basic techniques for locally naming values and procedures in Scheme, let and let*.

Preparation

a. Create a new 20x20 image and name it canvas. Zoom in to 800%.

b. Make sure that your library includes the spot procedures spot-new, spot-col, spot-row, spot-nudge-right, and image-render-spot!. (Follow the links for the code for the procedures.)

c. Load your library.

Exercises

Exercise 1: Evaluating let

What are the values of the following let-expressions? You may use DrScheme to help you answer these questions, but be sure you can explain how it arrived at its answers.

a.

(let ((tone "fa")
      (call-me "al"))
  (list call-me tone "l" tone))

b.

(let ((total (+ 8 3 4 2 7)))
  (let ((mean (/ total 5)))
    (* mean mean)))

c.

(let ((inches-per-foot 12)
      (feet-per-mile 5280.0))
  (let ((inches-per-mile (* inches-per-foot feet-per-mile)))
    (* inches-per-mile inches-per-mile)))

Exercise 2: Nesting Lets

a. Write a nested let-expression that binds a total of five names, alpha, beta, gamma, delta, and epsilon, with alpha bound to a spot of your choice (such as (spot-new 1 1 "red")) and each subsequent name bound to a spot one column to the right (computed by spot-nudge-right). That is, beta should be a column to the right of alpha, gamma a column to the right of beta, and so on and so forth. The body of the innermost let should list the five spots.

Your result will look something like

(let ((...))
  (let ((...))
    (let ((...))
      (let ((...))
        (let ((...))
	  (list alpha beta gamma delta epsilon))))))

b. Name the result of the computation using define.

(define spots
  (let ((...))
    (let ((...))
      (let ((...))
        (let ((...))
          (let ((...))
	    (list alpha beta gamma delta epsilon)))))))
c. Put the spots on canvas with
(foreach! (lambda (spot) (image-render-spot! canvas spot)) spots)

Exercise 3: Simplifying Nested Lets

a. Write a let*-expression equivalent to the let-expression in the previous exercise, but using a different starting spot.

b. Repeat steps b and c of the previous exercise.

Exercise 4: Detour: Printing Values

Sometimes it's useful to see values as they are being computed. Here's a procedure that makes it easy to tell when an expression is being used. It prints the value it is called with and then returns the value.

(define value
  (lambda (val) 
    (display "Computed: ")
    (display val)
    (newline)
    val))

a. What do you expect to happen when you execute the following command?

(+ (value 5) (value 7))

b. Check your answer experimentally.

c. What do you expect to happen when you execute the following command?

(* (value (+ (value 2) (value 3))) (value (+ (value 1) (value 1))))

d. Check your answer experimentally.

e. What do you expect to happen when you execute the following command?

(define tmp (value (* 3 4 5)))

Exercise 5: Ordering Bindings

In the reading, we noted that it is possible to move bindings outside of the lambda in a procedure definition. In particular, we noted that the first of the two following versions of years-to-seconds required recomputation of seconds-per-year every time it was called while the second required that computation only once.

(define years-to-seconds
  (lambda (years)
    (let* ((days-per-year 365.24)
           (hours-per-day 24)
           (minutes-per-hour 60)
           (seconds-per-minute 60)
           (seconds-per-year (* days-per-year hours-per-day
                                minutes-per-hour seconds-per-minute)))
      (* years seconds-per-year))))

(define years-to-seconds
  (let* ((days-per-year 365.24)
         (hours-per-day 24)
         (minutes-per-hour 60)
         (seconds-per-minute 60)
         (seconds-per-year (* days-per-year hours-per-day
                              minutes-per-hour seconds-per-minute)))
    (lambda (years)
      (* years seconds-per-year))))

a. Rename the first version years-to-seconds-a and the second years-to-seconds-b.

b. Using value, confirm that years-to-seconds-a does, in fact, recompute the values each time it is called. You might, for example, replace

           (seconds-per-year (* days-per-year hours-per-day 
                                minutes-per-hour seconds-per-minute)))

with

           (seconds-per-year (value (* days-per-year hours-per-day 
                                       minutes-per-hour seconds-per-minute))))

c. Confirm that years-to-seconds-b does not recompute the values each time it is called. Again, make changes like those reported above.

d. Given that years-to-seconds-b does not recompute each time, when does it do the computation? (Consider when you see the messages.)

Exercise 6: Ordering Bindings, Revisited

You may recall that we defined a procedure to compute a grey with the same brightness as a given color.

(define rgb-greyscale
  (lambda (color)
    (let ((component (+ (* 0.30 (rgb-red color)) 
                        (* 0.59 (rgb-green color))
                        (* 0.11 (rgb-blue color)))))
      (rgb-new component component component))))

You might be tempted to move the let clause outside the lambda, just as we did in the previous exercise. However, as we noted in this reading, this reordering will fail.

a. Verify that it will not work to move the let before the lambda, as in

(define rgb-greyscale
  (let ((brightness (+ (* 0.30 (rgb-red color)) 
                       (* 0.59 (rgb-green color))
                       (* 0.11 (rgb-blue color)))))
    (lambda (color)
      (rgb-new brightness brightness brightness))))

b. Explain, in your own words, why this fails (and why it should fail).

For Those With Extra Time

Forthcoming.

Creative Commons License

Samuel A. Rebelsky, rebelsky@grinnell.edu

Copyright (c) 2007-8 Janet Davis, Matthew Kluber, and Samuel A. Rebelsky. (Selected materials copyright by John David Stone and Henry Walker and used by permission.)

This material is based upon work partially supported by the National Science Foundation under Grant No. CCLI-0633090. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.

This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/2.5/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.