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.)

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))
```

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

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

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.

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.