SICP 3.1.1 Exercises

March 12, 2017 17:49

In Chapter 3, a completely new concept is introduced — storing values to create a local state. This changes our programs so that they have memory and can change over time. As we’ll see, that has benefits and drawbacks.

For these exercises, the tests are back to a simpler form. They won’t be wrapped in lambda statements, which means that any errors will cause the program to exit. This is partly to keep things simple for the new chapter, and partly to better understand how assignment affects the testing process. Since later tests will depend on the state of things after earlier tests, it’s better to exit as soon as one fails than to continue into potential chaos.

With the ability to have a local state in our programs, performing operations during the test itself may change that state. Previously, we could run our tests with any value and in any order, and the results of one test had no affect on any of the other tests. We now have to be aware of what the test operation does, and may need to pay attention to the order of the operations within a test.

This is not wholly undesirable behavior. In fact, much of the time we will want to run a test to determine that desired changes in state actually do occur. Thus, following a sequence of operations will be a critical part of our testing toolkit.

That said, there are aspects related to state that we don’t want to worry about during testing. If we always need to monitor the state in order to write our tests, it becomes harder to modify the tests — adding or removing a single test might make it necessary to rewrite every test that follows after it. Not only that, but it can mean we aren’t testing our code as well as we thought, since the test might only be applicable to a very particular sequence that does not always occur in practice.

In this section, the tests are short and the sequences are not too hard to follow. Therefore some tests will go in sequence; I’ve tried to note when they rely on the current state. In future sections, we’ll sometimes need to pay attention to the stored state during testing so that we aren’t expending effort to keep track of the system’s state when it’s not important to us.

One exercise in this section provides a demonstration of how assignment and state can be of real help in our testing. By having procedures that store values in a testing context, we can monitor the process under test, and even gain information about it without having to change the underlying code. Indeed the ‘test state’ storage function will be put to use for testing, just two exercises after it is written. In that exercise, a monitored version will be used to determine whether the procedure that was expected to be run (call-the-cops) actually was.

Note that the testing code depends on being able to redefine existing variables; if your version of Scheme doesn’t allow this, the code won’t work as written and renaming will be required. The monitored version also expects that call-the-cops does not take any arguments, which isn’t one of its requirements in the exercise. However, there isn’t likely to be any need for an argument in any version you come up with. Alternatively, if you do have call-the-cops take an argument, you can modify the monitoring routine to handle it.

Exercises 3.1.1