| 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 programs violation of the abstraction provided by the packagein 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. Adas 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 |