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
   B’s 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 => “B’s 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