%CustomEntities; %CourseEntities; %CommonEntities; ]>
Laboratory: Verifying Preconditions Summary: In this laboratory, you will consider mechanisms for verifying the preconditions of procedures. You will also consider some issues in the documentation of such procedures.
Preparation a. Open up your library and verify that it includes spot-new, spot-col, spot-row, and spot-color. If you are missing any of those procedures, add them. b. As you may recall from the reading, we will be checking if values are spots (or at least whether they can be interepreted as spots). You may find the following procedure valuable for checking that precondition. Add it to your library. c. Create another tab or window for doing this lab. At the top of your definitions pane, add a command to load your library. d. In the reading, we worked with the example of finding the leftmost spot in a list of spots. Add the following code to your definitions pane.
Exercises
Exercise 1: Are They All Spots? You may have noted that spots-leftmost requires an all-spots? procedure. Here's a definition. a. What preconditions should all-spots? have? b. Is it necessary to test those preconditions? Why or why not? c. Compare your answers to the those in notes at the end of this lab. d. Document the all-spots? procedure.
Exercise 2: Exploring Errors a. Verify that spots-leftmost returns an appropriate error when given incorrect inputs. b. In the corresponding reading, there is an extended version of spots-leftmost that reports different errors. Replace your current spots-leftmost with the new version and verify that it does, in fact, report different errors.
Exercise 3: Finding Values Here is a procedure, index-of, that takes a value, val, and a list, vals, as its arguments and returns the index of val in vals. And here are some examples of index-of in use. > (index-of color-red (list color-red color-green color-blue color-yellow)) 0 > (index-of color-blue (list color-red color-green color-blue color-yellow)) 2 a. What preconditions should index-of have? b. Arrange for index-of to explicitly signal an error (by invoking the throw procedure) if vals is not a list. c. Arrange for index-of to explicitly signal an error (by invoking the throw procedure) if val does not occur at all as an element of vals. > (index-of color-black (list color-red color-green color-blue color-yellow)) Error: The value does not appear in the list. d. Some programmers return special values to signal an error to the caller, rather than throw an error. If val does not occur as an element of vals, why might it be better to have index-of return a special value (such as -1 or #f) rather than throwing an error? Explain your answer. e. If val does not occur as an element of vals, why might be better to have index-of throw an error? f. Once you have explained your answers do d and e, you may want to check our notes on this problem. g. Rewrite index-of using a husk-and-kernel strategy. When you're done thinking about these questions, add index-of to your library as it is a very useful procedure.
Exercise 4: Changing Colors Consider the following procedure that increments the red component of color by 64. a. What preconditions must be met in order for rgb-much-redder to meet its postconditions? b. Should we test those preconditions? Why or why not?
Exercise 5: Weighted Color Averages In a number of exercises, we were required to blend two colors. For example, we blended colors in a variety of ways to make interesting images, and we made a color more grey by averaging it with grey. In blending two colors, we are, in essence, creating an average of the two colors, but an average in which each color contributes a different fraction. For this problem, we might write a procedure, (rgb-weighted-average fraction color1 color2), that makes a new color, each of whose components is computed by multiplying the corresponding component of color1 by fraction and adding that to the result of multiplying the corresponding component of color2 by (1-fraction). For example, we might compute the red component with (+ (* fraction (rgb-red color1)) (* (- 1 fraction) (rgb-red color2))) a. What preconditions should rgb-weighted-average have? (Think about restrictions on fraction, color1, and color2.) b. How might you formally specify the postconditions for rgb-weighted-average? c. Here is a simple definition of rgb-weighted-average. Rewrite rgb-weighted-average to use a husk-and-kernel strategy to test for preconditions.
For Those With Extra Time
Extra 1: Substitution Consider a procedure, (list-substitute lst old new), that builds a new list by substituting new for old whenever old appears in lst. > (list-substitute (list "black" "red" "green" "blue" "black") "black" "white") ("white" "red" "green" "blue" "white") > (list-substitute (list "black" "red" "green" "blue" "black") "yellow" "white") ("black" "red" "green" "blue" "black") > (list-substitute null "yellow" "white") () a. Document this procedure, making sure to carefully consider the preconditions. b. Implement this procedure, making sure to check the preconditions.
Extra 2: Substituting Colors, Revisited Consider a procedure, (spots-substitute spots old new), that, given a list of spots and two colors, makes a new copy of spots by using the color new whenever old appeared in the original spots. a. What preconditions does this procedure have? b. Implement this procedure, using the husk-and-kernel structure to ensure that old and new are rgb colors and that spots is a list of spots, before starting the recursion.
Extra 3: <function>index-of</function>, Revisited Rewrite index-of using tail recursion and a husk and kernel.
Notes on the Problems
Notes on Problem 1: Are They All Spots? Here are some possible solutions. a. The all-spots? procedure needs a list as a parameter. b. It depends on how we will use all-spots?. If we are sure that it will only be called correctly (e.g., after we've already tested that the parameter is a list or in a context in which we can prove that the parameter is list), then it need not check its preconditions. Otherwise, it should check its preconditions. Return to the problem.
Notes on Exercise 3: Finding Values d. If index-of explicitly checks its precondition using member?, we end up duplicating work. That is, we scan the list once to see if the value is there, and once to see its index. Even if index-of does not explicitly check its precondition, the caller may be called upon to do so, which still duplicates the work. By having index-of return a special value, we permit the client to have index-of do both. e. In some cases, programs should stop when there is no index for a specified value. For example, a program that tries to look up a grade for a student should not continue if the student does not appear in the list. There are also some instances in which careless programmers do not check the return value, which can lead to unpredictable behavior. Return to the problem.