Previous | Table of Contents | Next |
10.4.2.4. Using the Rationals Package
Before I investigate the implementations of the rational-number packages, examine a typical interactive client program. A session with this program might be
A = 1/3 B = -2/4 Enter rational number C > 2/5 Enter rational number D > 3/4 E = A + B is -2/12 A + E * B is 60/144 Bs numerator is -2
Results such as -2/12 and 60/144 make it obvious that nothing in this package is reducing rationals to lowest terms. A good rationals package should do so; I have chosen to omit it in the interest of brevity. It would not be difficult to add to the / operator.
1 with Ada.Text_IO, Ada.Integer_Text_IO; 2 with HB.Rationals, HB.Rationals.IO; 3 use HB.Rationals; 4 procedure Show_Package is 5 6 A, B, C, D, E: Rational; 7 8 begin 9 10 A := 1/3; 11 B := 2/(-4); 12 Ada.Text_IO.Put(Item => A = ); 13 HB.Rationals.IO.Put(Item => A); 14 Ada.Text_IO.New_Line; 15 Ada.Text_IO.Put(Item => B = ); 16 HB.Rationals.IO.Put(Item => B); 17 Ada.Text_IO.New_Line; 18 19 Ada.Text_IO.Put(Item => Enter rational number C > ); 20 HB.Rationals.IO.Get(Item => C); 21 Ada.Text_IO.Put(Item => Enter rational number D > ); 22 HB.Rationals.IO.Get(Item => D); 23 Ada.Text_IO.New_Line; 24 25 E := A + B; 26 Ada.Text_IO.Put(Item => E = A + B is ); 27 HB.Rationals.IO.Put(Item => E); 28 Ada.Text_IO.New_Line; 29 30 Ada.Text_IO.Put(Item => A + E * B is ); 31 HB.Rationals.IO.Put(Item => A + E * B); 32 Ada.Text_IO.New_Line; 33 34 Ada.Text_IO.Put(Item => Bs numerator is ); 35 Ada.Integer_Text_IO.Put 36 (Item => Numer(B), Width => 1); 37 Ada.Text_IO.New_Line; 38 39 exception 40 when ZeroDenominator => 41 Ada.Text_IO.Put_Line(Item => 42 Zero not allowed in denominator; bye-bye.); 43 end Show_Package;
Lines 1-3 provide the expected context clauses and a use for Rationals. The use allows me to use the rational operators in infix form; without a use, I would have to say, for example, in line 10,
A := Rationals./(1,3);
which is unpleasant. The rest of the program illustrates some simple rational arithmetic; note line 25, for example, which looks like an ordinary arithmetic assignment, but in fact, all the operations are rational ones.
In analyzing E := A + B, the compiler can determine that the + is intended to be that for rationals because its two operands (A and B) are of type Rational, as is the return type (E). Similarly in line 31, the expression A + E * B is a rational one because all three operands are, as is the desired Item sent to HB.Rationals.IO.Put. Determining which of several like-named operators is intended is called overload resolution; the compiler can resolve the overloads if and only if it has enough information to do so.
If X is Integer and Y is Rational, the expression X + Y results in a compilation error. This is simply because there is no + defined for this combination of operands; I could add one to the package if I chose to do so; its line in the interface would be
function +(X: Integer; R: Rational) return Rational;
Indeed, nothing prevents me from writing a package providing other mixed operations, such as
function +(X: Integer; F: Float) return Float;
This observation reveals that although mixed operations are not predefined in Ada, you could add these to the language via a suitable (large) collection of overloaded operators. Doing so would not be desirable, however: The compiler would have no trouble resolving all the overloads in a program that used these mixed expressions, but the human reader would quickly get confused. Operator overloading is convenient when used in moderation.
Previous | Table of Contents | Next |