#### Packages

A **package** lets us group related declarations, procedures, and functions. A
program can **with** the package and gain access to all of these. However, as
we'll see, packages have many other advantages. Usually library units are
packages rather than individual procedures and functions.

By way of example, consider a very simple procedure and a very simple function:

procedure Double(Number : in Integer; Answer : out Integer); function Twice(Number : in Integer) return Integer;

We could compile these individually, or we could put them in a **package** and
compile that instead. Here's the package specification:

package Simple_Math is procedure Double(Number : in Integer; Answer : out Integer); function Twice(Number : in Integer) return Integer; end Simple_Math;

The package **body** must contain the bodies of all the procedures and functions
declared in the package specification:

package body Simple_Math is procedure Double(Number : in Integer; Answer : out Integer) is begin Answer := Number * 2; end Double; function Twice(Number : in Integer) return Integer is begin return Number * 2; end Twice; end Simple_Math;

The package body could optionally declare either or both subprograms to be
**separate**:

package body Simple_Math is procedure Double(Number : in Integer; Answer : out Integer) is separate; function Twice(Number : in Integer) return Integer is separate; end Simple_Math;

Here's an example of a calling program that **with**s the package and makes use of
the two subprograms declared in the package specification:

with Simple_Math; use Simple_Math; procedure Package_Demo is I, J : Integer := 10; begin Double(Number => I, Answer => J); -- This line sets J to 20. J := Twice(I); -- This line also sets J to 20. end Package_Demo;

The package specification must be compiled first, but either the calling
program or the package body may be compiled second. The calling program
depends only on the package **specification**, not the package **body**. Similarly,
the package body depends on the package specification. If the package body
declares any subprograms to be **separate**, these must be compiled after the
package body, because any **separate** subprogram depends on its "parent."

A package specification that declares no subprograms (only objects, types,
etc.) doesn't need a package body. In Ada 95, a package specification that
doesn't need a body may not have one, unless we include **pragma Elaborate_Body;**
in the package specification. We'll learn more about pragmas later.

The main program may never be inside a package. It must be a procedure or function compiled directly into the library, such as Hello or Add. In most implementations of Ada, the main program can't have any parameters, and must be a procedure rather than a function.

A package body may optionally have initialization code, introduced by the word
**begin**. This code is executed only once, the first time another program
elaborates the package by **with**ing it. For example, this package uses
initialization code to initialize the array B:

package P is function F return Float; end P; package body P is A : array(1 .. 10) of Float := (others => 0.0); B : array(1 .. 10, 1 .. 10) of Integer; function F return Float is ... end F; begin for I in 1 .. 10 loop for J in 1 .. 10 loop B(I, J) := I*J*J; end loop; end loop; end P;

Declarations made inside a package **specification** are said to be **exported** and
are available to programs outside the package that **with** the package. However,
declarations made inside the package **body** are available only inside the
package. The package body doesn't even have to be written before outside
programs that **with** the package. In this example, programs outside and inside
the package may use type Answer, array A, and procedure R, but only procedures
P, Q and R may use type Question and array B. Procedure P may be called only
by Q and R (and itself), and procedure Q is available only to R (and itself).

package X is type Answer is (Yes, No, Maybe); A : array(1 .. 10) of Float; procedure R; end X; package body X is type Question is (Why, Who, How); B : array(1 .. 10) of Integer; procedure P is separate; procedure Q is separate; procedure R is separate; end X;

#### Functions with Infix Notation

+ - * / ** & = < > <= >= and or xor abs not mod rem

Ada allows us to overload any of the above operators by enclosing the operator
in quotes following the word **function**. For example, having defined type Date,
we may want to define what it means for one date to be "less than" another. We
could write **function "<"(Left, Right : in Date) return Boolean;**. Then, our
program could declare **D1, D2 : Date;** and test **D1 < D2**. This test would call
our function "<", because **<** is used between two objects of type Date.
Similarly, we can overload "*" to give the dot product of two vectors:

type Vector is array(Integer range <>) of Float; V1, V2 : Vector(1 .. 100); X : Float; function "*"(Left, Right : in Vector) return Float is ... end "*"; ... X := V1 * V2; -- This calls our function "*".

There are some restrictions when using infix notation. First, all of the
operators above (except **abs**, **not**, **+**, and **-**) must be used between two
expressions, and thus the function specification must have exactly two
parameters. Traditionally, the two parameters are called Left and Right. The
operators **abs** and **not** must have just one expression on the right, and **+** and **-**
may have one expression on the right, or come between two expressions. These
restrictions come from the way the compiler handles operators. For example,
the compiler can handle **X := - X;**, but it's not designed to handle **X := * X;**.

Second, in Ada 83 the function "=" must return type Boolean, its two parameters
must be of the same type, and that type must be a limited private type, to be
discussed later. For all the types discussed so far, function "=" is **already defined** by Ada. Two records are equal if all of their corresponding fields are
equal, and two arrays are equal if they have the same length and all of their
corresponding elements are equal.

Note that in Ada 83 we can't redefine function "/=". However, if we redefine
"=" for some limited private type, we can use **/=**. Ada will call our function
"=" and negate the result. For example,

type Text is limited private; -- to be discussed later T1, T2 : Text; function "="(Left, Right : in Text) return Boolean is ... end "="; ... if T1 /= T2 then -- Calls our "=" and reverses the result. ... end if;

Also, in Ada 83 and Ada 95, we can't redefine **in**, **not in**, **and then**, **or else**, or
**:=**. Technically, these aren't operators.

In Ada 95, we may redefine **=**to return any type, not just Boolean. However, if
we do redefine **=** to return type Boolean, then we have automatically also
redefined **/=** to call our **=** and reverse the result.

If, on the other hand, we redefine **=** to return some type other than Boolean,
then **/=** is **not** automatically redefined.&mnsp; However, in this case Ada 95 lets us
separately redefine **/=** if we want to, and it may return any type.

Functions using infix notation can't be compiled directly into the library. They must either be declared locally inside a procedure or function, or placed inside a package. This is done because many implementations of Ada create files with names based on the name of the function, procedure, or package being compiled. Since many of the operators are punctuation marks, they would create file names that are illegal on most systems.

For the same reason, two functions or procedures with the same name can't be
compiled directly into the library; on many systems that would attempt to give
the same name to two different files. For example, the package specification
below is legal. However, the package body can't declare both Display's
separate, and it can't declare either "*" **separate**.

package P is type Complex is ... type Vector is ... procedure Display(C : in Complex); procedure Display(V : in Vector); function "*"(Left, Right : in Complex) return Complex; function "*"(Left, Right : in Vector) return Float; end P;

#### Question

package K is type Complex is record Re, Im : Float; end record; type Vector is array(Integer range <>) of Float; function "+"(Left, Right : in Complex) return Complex; function "*"(Left, Right : in Complex) return Complex; function "*"(Left, Right : in Vector) return Float; function Conjugate(C : in Complex) return Complex; procedure Display(C : in Complex); procedure Display(V : in Vector); end K;The above is a package specification. In the package body, how many subprograms could be made

**separate**: 0, 1, 2, 3, 4, 5, or 6?

## No comments:

Post a Comment