Previous Table of Contents Next


10.4.2.5. Implementing the Rationals and Rationals.IO Packages

Now examine the implementation of the Rationals package. In Ada, the implementation is called a package body, as line 1 shows.

    1 package body HB.Rationals is
    2
    3   function “/” (X, Y : Integer) return Rational is
    4   begin
    5     if Y = 0 then
    6       raise ZeroDenominator;
    7     elsif X = 0 then
    8       return (Numerator => 0, Denominator => 1);
    9     elsif Y > 0 then
   10       return (Numerator => X, Denominator => Y);
   11     else
   12       return (Numerator => -X, Denominator => -Y);
   13     end if;
   14   end “/”;
   15
   16   function Numer (R : Rational) return Integer is
   17   begin
   18     return R.Numerator;
   19   end Numer;
   20
   21   function Denom (R : Rational) return Positive is
   22   begin
   23     return R.Denominator;
   24   end Denom;
   25
   26   function “=” (R1, R2 : Rational) return Boolean is
   27   begin
   28     return Numer(R1)*Denom(R2) = Numer(R2)*Denom(R1);
   29   end “=”;
   30
   31   function “<” (R1, R2 : Rational) return Boolean is
   32   begin
   33     return Numer(R1)*Denom(R2) < Numer(R2)*Denom(R1);
   34   end “<”;
   35
   36   function “>” (R1, R2 : Rational) return Boolean is
   37   begin
   38     return Numer(R1)*Denom(R2) > Numer(R2)*Denom(R1);
   39   end “>”;
   40
   41   function “<=” (R1, R2 : Rational) return Boolean is
   42   begin
   43     return Numer(R1)*Denom(R2) <= Numer(R2)*Denom(R1);
   44   end “<=”;
   45
   46   function “>=” (R1, R2 : Rational) return Boolean is
   47   begin
   48     return Numer(R1)*Denom(R2) >= Numer(R2)*Denom(R1);
   49   end “>=”;
   50
   51   function “+”(R : Rational) return Rational is
   52   begin
   53     return R;
   54   end “+”;
   55
   56   function “-”(R : Rational) return Rational is
   57   begin
   58     return (-Numer(R)) / Denom(R);
   59   end “-”;
   60
   61   function “abs”(R : Rational) return Rational is
   62   begin
   63     return (abs Numer(R)) / Denom(R);
   64   end “abs”;
   65
   66   function “+”(R1, R2 : Rational) return Rational is
   67   begin
   68     return (Numerator =>
   69               Numer(R1)*Denom(R2) + Numer(R2)*Denom(R1),
   70             Denominator => Denom(R1)*Denom(R2));
   71   end “+”;
   72
   73   function “-”(R1, R2 : Rational) return Rational is
   74   begin
   75     return (Numerator =>
   76               Numer(R1)*Denom(R2) - Numer(R2)*Denom(R1),
   77             Denominator => Denom(R1)*Denom(R2));
   78   end “-”;
   79
   80   function “*”(R1, R2 : Rational) return Rational is
   81   begin
   82     return (Numerator => Numer(R1)*Numer(R2),
   83             Denominator => Denom(R1)*Denom(R2));
   84   end “*”;
   85
   86   function “/”(R1, R2 : Rational) return Rational is
   87   begin
   88     return (Denominator => Numer(R1)*Numer(R2),
   89             Numerator => Denom(R1)*Denom(R2));
   90   end “/”;
   91
   92 end HB.Rationals;

Lines 3-14 implement the “/” operator. This is simply a matter of checking the various cases. In the first case (line 6), an attempt to store 0 in the denominator, we

   raise ZeroDenominator;

Because there is no exception handler in this function, the exception is propagated to the point where the client called the function. If the client provides a nearby handler, control is passed to it; otherwise, control passes to the next higher level in the call chain and so forth until either the exception is handled somewhere in the application or it passes beyond the main program to the runtime system.

It is quite common in Ada to declare exceptions in package interfaces and then raise them in package implementations. This sort of exception responds to a client program’s violation of the abstraction provided by the package—in this case, the mathematical prohibition against 0 in the denominator of a rational number. The package cannot be expected to “clean up” a violation such as this: The client caused the problem and the client is responsible for solving it. Ada’s exception-propagation rules encourage programmers to design such that responsibility for anomalies and violations is passed to, and handled by, just the right layer of the overall program.


Previous Table of Contents Next