In this section the generic arithmetic package continues to expand. It will now allow operations that mix the types of numbers allowed. While the system works nearly identically to the one in 2.5.1, there are some new types that the exercises rely on. To avoid crowding the definitions into the exercise file, both the new types and the tests that deal with them have been moved into separate files. These two are called ‘gen-arith252.scm’ and ‘gen-arith-tests_v2.scm’, and are located in the library directory. The tests have been rewritten so that they can apply to the old system (which is used in the first two exercises) and the new ‘tower’ system of hierarchical types.
There is one wrinkle in this: the Integer type will fail some of the arithmetic property tests, because integer division does not always produce an integer result. It would probably be best to further separate the arithmetic property tests into addition and multiplication tests, but since we can run failing tests without exiting the program, I’m overlooking it in this case. There is also a hack at the start of the file that lets us use the new tests on the original system, by letting Scheme numbers stand in for Integer and Real types.
In Exercise 2.82 we deal with operations that require an arbitrary number of arguments. While I did define a new operation to test how coercion may work, I have not included any operation that takes more than two arguments. For this case, using the previous tests should suffice, although you are free to add more tests to ensure that an added operation actually works with multiple arguments.
I also want to explain a feature of the tower/hierarchical system that I included for testing in Exercises 2.83 and later. In order to have a progression from rationals to reals (and back), an arbitrary ‘rationalization’ can be performed on a real. This allows it to be expressible as a fraction (rational) as long as there is an equivalent (sidenote) ‘equivalent’ as defined by
equ? fractional representation that does not require a denominator larger than a given number. The cutoff for denominator size is arbitrary because all values of the Real type, which internally are floating-point values, are actually just high-precision fractions and could thus always be expressed as some sort of Rational.
Implementing this feature requires using
getdenom to project a Real in Exercise 2.85. The alternative is to simply disallow dropping of Reals to Rationals. This is acceptable, but be aware that some of the tests I’ve written may fail if that is the case. A few examples are included to show how the determination of the denominator works. Different systems will not necessarily ‘reduce’ in the same way, due to the internal representaion
As the exercises go on, there are continual changes to the system. Each time we can go back and run the same basic tests. Because the system interface remains the same, the tests continue to work, and this ensures we didn’t wreck anything that was previously working. Typically, a few new tests are added to verify the specific feature just added or modified.
In truth, the number of additional tests I’ve written really do not do enough to fully exercise the system, but as this section is fairly intensive, and I’ve already spent far too long working on just the solutions, I didn’t want to add even more tests that might need to be figured out. Hopefully by this point you’re able to identify what features to look for and can write a few tests of your own. It’s never wrong to go back and modify the tests themselves as the system develops and changes.