This section presents an “example”, which is a more practical application of the methods studied in the text so far. Often the examples require a bit of extra effort to fully implement, and this one is definitely no exception. Most obviously, we need a simple way to display graphics that we can draw. Here is where a pre-defined library of graphic routines would really help.
Luckily, this does exist if you’re using Racket (and I believe there are options for other varieties of Scheme if you poke around for them). These exercises make use of the tailor-made SICP picture language package, for which the documentation is here . What I like best about this is that when something is painted, it simply appears as a small (128×128) picture in the output window. This allows for easy interaction with the interpreter, which is a big help when trying to figure out the exercises.
The package does not require painters to use a frame for output. The routine
paint, called using
(paint some-painter), will return a ‘snip’, which can be directly displayed. But this also has the drawback that we can’t use
(painter frame) and have the output appear, which is how the text would have it. For this purpose I added a helper function
paint-with-frame that will output a snip of a painter painted in its frame. Most of the time the snip is output simply by being the result of a function, but it can also be output using
The text mentions but does not define
draw-line, which is another addition in this file. It relies on the definitions for vectors that are produced from Exercise 2.46. Painters used before that use the built-in ones
einstein (a less-MIT-centric analog to the text’s Mr. Rogers), which don’t need
draw-line at all. Indeed, only the painters built using segments actually require it.
It’s no surprise that the package also implements most of the very procedures required in the exercises. This isn’t too much of a concern, as we can rename the package’s procedures and then redefine them as needed.
One real point of difficulty is that due to the differences in painter and frame implementation, the package’s predefined painters aren’t compatible with the ones we might create. There is a conversion routine
painter->soegaard-painter which allows us to use the same routines for both our own shapes (as defined in Exercise 2.49) and the predefined ones. This converter requires a
painter and a
frame and produces a painter that works in the way the package’s do (i.e. without a frame). It ends up being a bit unfortunate that we are muddling the definition of what a painter is, but that’s the price we pay for making use of someone else’s library.
The difference in painters also requires using the package’s version of
transform-painter so that we don’t end up converting our painters to the wrong type. There is another point of variation here in that the package’s
transform-painter does not take a
painter as an argument, but instead produces a function that operates on a painter. Again, this is an arguably sensible decision, but I try to maintain compatibility by defining a new version that works the same as the text’s, meaning the exercises can follow the pattern of the transformations given in the book.
In the last exercise, I make use of the alternate form
paint-hi-res, which is like
paint but uses a drawing area four times the size, and might be preferable for the detailed images that functions like