# Ada Programming/Type System

Ada\'s type system allows the programmer to construct powerful
abstractions that represent the real world, and to provide valuable
information to the compiler, so that the compiler can find many logic or
design errors before they become bugs. It is at the heart of the
language, and good Ada programmers learn to use it to great advantage.
Four principles govern the type system:

-   **Type**: a way to categorize data. characters are types \'a\'
    through \'z\'. Integers are types that include 0,1,2\....
-   **Strong typing**: types are incompatible with one another, so it is
    not possible to mix apples and oranges. The compiler will not guess
    that your apple is an orange. You must explicitly say my_fruit =
    fruit(my_apple). Strong typing reduces the amount of errors. This is
    because developers can really easily write a float into an integer
    variable without knowing. Now data you needed for your program to
    succeed has been lost in the conversion when the complier switched
    types. Ada gets mad and rejects the developer\'s dumb mistake by
    refusing to do the conversion unless explicitly told.
-   **Static typing**: type checked while compiling, this allows type
    errors to be found earlier.
-   **Abstraction**: types represent the real world or the problem at
    hand; not how the computer represents the data internally. There are
    ways to specify exactly how a type must be represented at the bit
    level, but we will defer that discussion to another chapter. An
    example of an abstraction is your car. You don\'t really know how it
    works you just know that bumbling hunk of metal moves. Nearly every
    technology you work with is abstracted layer to simplify the complex
    circuits that make it up - the same goes for software. You want
    abstraction because code in a class makes a lot more sense than a
    hundred if statements with no explanation when debugging
-   **Name equivalence**, as opposed to *structural equivalence* used in
    most other languages. Two types are compatible if and only if they
    have the same name; *not* if they just happen to have the same size
    or bit representation. You can thus declare two integer types with
    the same ranges that are totally incompatible, or two record types
    with exactly the same components, but which are incompatible.

Types are incompatible with one another. However, each type can have any
number of *subtypes*, which are compatible with their base type and may
be compatible with one another. See below for examples of subtypes which
are incompatible with one another.

## Predefined types

There are several predefined types, but most programmers prefer to
define their own, application-specific types. Nevertheless, these
predefined types are very useful as interfaces between libraries
developed independently. The predefined library, obviously, uses these
types too.

These types are predefined in the
package:

Integer: This type covers at least the range $-2^{15}+1$ .. $+2^{15}-1$ (RM ). The Standard also defines `Natural` and `Positive` subtypes of this type.

Float: There is only a very weak implementation requirement on this type (RM ); most of the time you would define your own floating-point types, and specify your precision and range requirements.\
Duration: A fixed point type used for timing. It represents a period of time in seconds (RM ).\
Character : A special form of Enumerations. There are three predefined kinds of character types: 8-bit characters (called `Character`), 16-bit characters (called `Wide_Character`), and 32-bit characters (`Wide_Wide_Character`). `Character` has been present since the first version of the language (Ada 83), `Wide_Character` was added in Ada 95, while the type `Wide_Wide_Character` is available with Ada 2005.\
String: Three indefinite array types, of `Character`, `Wide_Character`, and `Wide_Wide_Character` respectively. The standard library contains packages for handling strings in three variants: fixed length (), with varying length below a certain upper bound (), and unbounded length (). Each of these packages has a `Wide_` and a `Wide_Wide_` variant.\
Boolean : A `Boolean` in Ada is an Enumeration of `False` and `True` with special semantics.

Packages  and
 predefine some
types which are primarily useful for low-level programming and
interfacing to hardware.

System.Address : An address in memory.\
System.Storage_Elements.Storage_Offset : An offset, which can be added to an address to obtain a new address. You can also subtract one address from another to get the offset between them. Together, `Address`, `Storage_Offset` and their associated subprograms provide for address arithmetic.\
System.Storage_Elements.Storage_Count : A subtype of `Storage_Offset` which cannot be negative, and represents the memory size of a data structure (similar to C\'s `size_t`).\
System.Storage_Elements.Storage_Element : In most computers, this is a byte. Formally, it is the smallest unit of memory that has an address.\
System.Storage_Elements.Storage_Array : An array of `Storage_Element`s without any meaning, useful when doing raw memory access.

## The Type Hierarchy

Types are organized hierarchically. A type inherits properties from
types above it in the hierarchy. For example, all scalar types (integer,
enumeration, modular, fixed-point and floating-point types) have
operators
\"\", \"\" and
arithmetic operators defined for them, and all discrete types can serve
as array indexes.

!Ada type hierarchy{width="550"}

Here is a broad overview of each category of types; please follow the
links for detailed explanations. Inside parenthesis there are
equivalences in C and Pascal for readers familiar with those languages.

Signed Integers `<small>`{=html}(**int**, **INTEGER**)`</small>`{=html} : Signed Integers are defined via the range of values needed.\
Unsigned Integers `<small>`{=html}(**unsigned**, **CARDINAL**)`</small>`{=html} : Unsigned Integers are called Modular Types. Apart from being unsigned they also have wrap-around functionality.\
Enumerations `<small>`{=html}(**enum**, **char**, **bool**, **BOOLEAN**)`</small>`{=html} : Ada Enumeration types are a separate type family.\
Floating point `<small>`{=html}(**float**, **double**, **REAL**)`</small>`{=html} : Floating point types are defined by the digits needed, the relative error bound.\
Ordinary and Decimal Fixed Point `<small>`{=html}(**DECIMAL**)`</small>`{=html} : Fixed point types are defined by their delta, the absolute error bound.\
Arrays `<small>`{=html}( **\[ \]**, **ARRAY \[ \] OF**, **STRING** )`</small>`{=html} : Arrays with both compile-time and run-time determined size are supported.\
Record `<small>`{=html}(**struct**, **class**, **RECORD OF**)`</small>`{=html} : A **record** is a composite type that groups one or more fields.\
Access `<small>`{=html}(**\***, **\^**, **POINTER TO**)`</small>`{=html} : Ada\'s Access types may be more than just a simple memory address.\
Task & Protected `<small>`{=html}(similar to multithreading in C++)`</small>`{=html} : Task and Protected types allow the control of concurrency\
Interfaces `<small>`{=html}(similar to virtual methods in C++)`</small>`{=html} : New in Ada 2005, these types are similar to the Java interfaces.

### Classification of Types

Ada\'s types can be classified as follows.

**Specific vs. Class-wide**

` T `` ...  -- a specific type`\
`  T'Class      -- the corresponding class-wide type (exists only for tagged types)`

`T'Class` and `T'Class'Class` are the same.

Primitive operations with parameters of specific types are
*non-dispatching*, those with parameters of class-wide types are
*dispatching*.

New types can be declared by *deriving* from specific types; primitive
operations are *inherited* by derivation. You cannot derive from
class-wide types.

**Constrained vs. Unconstrained**

` I `` `` 1 .. 10;           -- constrained`\
` AC `` `` (1 .. 10) `` ...  -- constrained`

` AU `` `` (I `` <>) `` ...          -- unconstrained`\
` R (X: Discriminant [:= Default]) `` ...  -- unconstrained`

By giving a *constraint* to an unconstrained subtype, a subtype or
object becomes constrained:

` RC `` R (Value);  -- constrained subtype of R`\
`OC: R (Value);            -- constrained object of anonymous constrained subtype of R`\
`OU: R;                    -- unconstrained object`

Declaring an unconstrained object is only possible if a default value is
given in the type declaration above. The language does not specify how
such objects are allocated. GNAT allocates the maximum size, so that
size changes that might occur with discriminant changes present no
problem. Another possibility is implicit dynamic allocation on the heap
and re-allocation followed by a deallocation when the size changes.

**Definite vs. Indefinite**

` I `` `` 1 .. 10;                     -- definite`\
` RD (X: Discriminant := Default) `` ...  -- definite`

` T (<>) `` ...                    -- indefinite`\
` AU `` `` (I `` <>) `` ...  -- indefinite`\
` RI (X: Discriminant) `` ...      -- indefinite`

Definite subtypes allow the declaration of objects without initial
value, since objects of definite subtypes have constraints that are
known at creation-time. Object declarations of indefinite subtypes need
an initial value to supply a constraint; they are then constrained by
the constraint delivered by the initial value.

`OT: T  := Expr;                       -- some initial expression (object, function call, etc.)`\
`OA: AU := (3 => 10, 5 => 2, 4 => 4);  -- index range is now 3 .. 5`\
`OR: RI := Expr;                       -- again some initial expression as above`

**Unconstrained vs. Indefinite**

Note that unconstrained subtypes are not necessarily indefinite as can
be seen above with RD: it is a definite unconstrained subtype.

## Concurrency Types

The Ada language uses types for one more purpose in addition to
classifying data + operations. The type system integrates concurrency
(threading, parallelism). Programmers will use types for expressing the
concurrent threads of control of their programs.

The core pieces of this part of the type system, the **task** types and
the **protected** types are explained in greater depth in a section on
tasking.

## Limited Types

Limiting a type means disallowing assignment. The "concurrency types"
described above are always limited. Programmers can define their own
types to be limited, too, like this:

` T `` `` …;`

(The ellipsis stands for , or for a
 definition, see the corresponding
subsection on this page.) A limited type also doesn\'t have an equality
operator unless the programmer defines one.

You can learn more in the limited
types chapter.

## Defining new types and subtypes

You can define a new type with the following syntax:

` T ``...`

followed by the description of the type, as explained in detail in each
category of type.

Formally, the above declaration creates a type and its *first subtype*
named `T`. The type itself, correctly called the \"type of T\", is
anonymous; the RM refers to it as *`T`* (in italics), but often speaks
sloppily about the type T. But this is an academic consideration; for
most purposes, it is sufficient to think of `T` as a type. For scalar
types, there is also a base type called `T'Base`, which encompasses all
values of T.

For signed integer types, the type of T comprises the (complete) set of
mathematical integers. The base type is a certain hardware type,
symmetric around zero (except for possibly one extra negative value),
encompassing all values of T.

As explained above, all types are incompatible; thus:

` Integer_1 `` `` 1 .. 10;`\
` Integer_2 `` `` 1 .. 10;`\
`A : Integer_1 := 8;`\
`B : Integer_2 := A; `

is illegal, because `Integer_1` and `Integer_2` are different and
incompatible types. It is this feature which allows the compiler to
detect logic errors at compile time, such as adding a file descriptor to
a number of bytes, or a length to a weight. The fact that the two types
have the same range does not make them compatible: this is *name
equivalence* in action, as opposed to structural equivalence. (Below, we
will see how you can convert between incompatible types; there are
strict rules for this.)

### Creating subtypes

You can also create new subtypes of a given type, which will be
compatible with each other, like this:

` Integer_1 `` `` 1 .. 10;`\
` Integer_2 `` Integer_1      `` 7 .. 11;  `\
` Integer_3 `` Integer_1'Base `` 7 .. 11;  `\
`A : Integer_1 := 8;`\
`B : Integer_3 := A; `

The declaration of `Integer_2` is bad because the constraint `7 .. 11`
is not compatible with `Integer_1`; it raises `Constraint_Error` at
subtype elaboration time.

`Integer_1` and `Integer_3` are compatible because they are both
subtypes of the same type, namely `Integer_1'Base`.

It is not necessary that the subtype ranges overlap, or be included in
one another. The compiler inserts a run-time range check when you assign
A to B; if the value of A, at that point, happens to be outside the
range of `Integer_3`, the program raises `Constraint_Error`.

There are a few predefined subtypes which are very useful:

` Natural  `` Integer `` 0 .. Integer'Last;`\
` Positive `` Integer `` 1 .. Integer'Last;`

### Derived types

A derived type is a new, full-blown type created from an existing one.
Like any other type, it is incompatible with its parent; however, it
inherits the primitive operations defined for the parent type.

` Integer_1 `` `` 1 .. 10;`\
` Integer_2 `` `` Integer_1 `` 2 .. 8;`\
`A : Integer_1 := 8;`\
`B : Integer_2 := A; `

Here both types are discrete; it is mandatory that the range of the
derived type be included in the range of its parent. Contrast this with
subtypes. The reason is that the derived type inherits the primitive
operations defined for its parent, and these operations assume the range
of the parent type. Here is an illustration of this feature:

` Derived_Types `\
\
`   `` Pak `\
`      `` Integer_1 `` `` 1 .. 10;`\
`      `` P (I: `` Integer_1); `\
`      `` Integer_2 `` `` Integer_1 `` 8 .. 10; `\
`      `\
`   `` Pak;`\
\
`   `` `` Pak `\
`      `\
`   `` Pak;`\
\
`   `` Pak;`\
`   A: Integer_1 := 4;`\
`   B: Integer_2 := 9;`\
\
\
\
`   P (B); `\
\
` Derived_Types;`

When we call `P (B)`, the parameter B is converted to `Integer_1`; this
conversion of course passes since the set of acceptable values for the
derived type (here, 8 .. 10) must be included in that of the parent type
(1 .. 10). Then P is called with the converted parameter.

Consider however a variant of the example above:

` Derived_Types `\
\
`  `` Pak `\
`    `` Integer_1 `` `` 1 .. 10;`\
`    `` P (I: `` Integer_1; J: `` Integer_1);`\
`    `` Integer_2 `` `` Integer_1 `` 8 .. 10;`\
`  `` Pak;`\
\
`  `` `` Pak `\
`    `` P (I: `` Integer_1; J: `` Integer_1) `\
`    `\
`      J := I - 1;`\
`    `` P;`\
`  `` Pak;`\
\
`  `` Pak;`\
\
`  A: Integer_1 := 4;  X: Integer_1;`\
`  B: Integer_2 := 8;  Y: Integer_2;`\
\
\
\
`  P (A, X);`\
`  P (B, Y);`\
\
` Derived_Types;`

When `P (B, Y)` is called, both parameters are converted to `Integer_1`.
Thus the range check on J (7) in the body of P will pass. However on
return parameter Y is converted back to `Integer_2` and the range check
on Y will of course fail.

With the above in mind, you will see why in the following program
Constraint_Error will be called at run time, before `P` is even called.

` Derived_Types `\
\
`  `` Pak `\
`    `` Integer_1 `` `` 1 .. 10;`\
`    `` P (I: `` Integer_1; J: `` Integer_1);`\
`    `` Integer_2 `` `` Integer_1'Base `` 8 .. 12;`\
`  `` Pak;`\
\
`  `` `` Pak `\
`    `` P (I: `` Integer_1; J: `` Integer_1) `\
`    `\
`      J := I - 1;`\
`    `` P;`\
`  `` Pak;`\
\
`  `` Pak;`\
\
`  B: Integer_2 := 11;  Y: Integer_2;`\
\
\
\
`  P (B, Y);`\
\
` Derived_Types;`

## Subtype categories

Ada supports various categories of subtypes which have different
abilities. Here is an overview in alphabetical order.

### Anonymous subtype

A subtype which does not have a name assigned to it. Such a subtype is
created with a variable declaration:

`X : String (1 .. 10) := (`` => ' ');`

Here, (1 .. 10) is the constraint. This variable declaration is
equivalent to:

` Anonymous_String_Type `` String (1 .. 10);`\
\
`X : Anonymous_String_Type := (`` => ' ');`

### Base type

In Ada, all types are anonymous and only
subtypes may be named. For scalar types,
there is a special subtype of the anonymous type, called the *base
type*, which is nameable with the \'
attribute. The base type comprises all values of the *first subtype*.
Some examples:

` `` Int `` `` 0 .. 100;`

The base type `Int'Base` is a hardware type selected by the compiler
that comprises the values of `Int`. Thus it may have the range -2^7^ ..
2^7^-1 or -2^15^ .. 2^15^-1 or any other such type.

` `` Enum  `` (A, B, C, D);`\
` `` Short `` `` Enum `` A .. C;`

`Enum'Base` is the same as `Enum`, but `Short'Base` also holds the
literal `D`.

### Constrained subtype

A subtype of an indefinite subtype that adds constraints. The following
example defines a 10 character string sub-type.

` `` String_10 `` String (1 .. 10);`

You cannot partially constrain an unconstrained subtype:

` `` My_Array `` `` (Integer `` <>, Integer `` <>) `` Some_Type;`\
\
` -- `` Constr `` My_Array (1 .. 10, Integer `` <>);  illegal`\
\
` `` Constr `` My_Array (1 .. 10, -100 .. 200);`

Constraints for all indices must be given, the result is necessarily a
definite subtype.

### Definite subtype

A definite subtype is a subtype whose size is known at compile-time. All
subtypes which are not indefinite subtypes are, by definition, definite
subtypes.

Objects of definite subtypes may be declared without additional
constraints.

### Indefinite subtype

An **indefinite subtype** is a subtype whose size is not known at
compile-time but is dynamically calculated at run-time. An indefinite
subtype does not by itself provide enough information to create an
object; an additional constraint or explicit initialization expression
is necessary in order to calculate the actual size and therefore create
the object.

`X : String := "This is a string";`

`X` is an object of the indefinite (sub)type `String`. Its constraint is
derived implicitly from its initial value. `X` may change its value, but
not its bounds.

It should be noted that it is not necessary to initialize the object
from a literal. You can also use a function. For example:

`X : String := Ada.Command_Line.Argument (1);`

This statement reads the first command-line argument and assigns it to
`X`.

A subtype of an indefinite subtype that does not add a constraint only
introduces a new name for the original subtype (a kind of renaming under
a different notion).

` `` My_String `` String;`

`My_String` and `String` are interchangeable.

### Named subtype

A subtype which has a name assigned to it. "First subtypes" are created
with the keyword  (remember that types are
always anonymous, the name in a type declaration is the name of the
first subtype), others with the keyword
. For example:

` Count_To_Ten `` `` 1 .. 10;`

`Count_to_Ten` is the first subtype of a suitable integer base type.
However, if you would like to use this as an index constraint on
`String`, the following declaration is illegal:

` Ten_Characters `` String (Count_to_Ten);`

This is because `String` has `Positive` as its index, which is a subtype
of `Integer` (these declarations are taken from package `Standard`):

` Positive `` Integer `` 1 .. Integer'Last;`\
\
` String `` (Positive `` <>) `` Character;`

So you have to use the following declarations:

` Count_To_Ten `` Integer `` 1 .. 10;`\
` Ten_Characters `` String (Count_to_Ten);`

Now `Ten_Characters` is the name of that subtype of `String` which is
constrained to `Count_To_Ten`. You see that posing constraints on types
versus subtypes has very different effects.

### Unconstrained subtype

Any indefinite type is also an unconstrained subtype. However,
unconstrainedness and indefiniteness are not the same.

` `` My_Enum `` (A, B, C);`\
` `` My_Record (Discriminant: My_Enum) `` ...;`\
\
` My_Object_A: My_Record (A);`

This type is unconstrained and indefinite because you need to give an
actual discriminant for object declarations; the object is constrained
to this discriminant which may not change.

When however a default is provided for the discriminant, the type is
definite yet unconstrained; it allows to define both, constrained and
unconstrained objects:

` `` My_Enum `` (A, B, C);`\
` `` My_Record (Discriminant: My_Enum := A) `` ...;`\
\
` My_Object_U: My_Record;      -- unconstrained object`\
` My_Object_B: My_Record (B);  -- constrained to discriminant B like above`

Here, My_Object_U is unconstrained; upon declaration, it has the
discriminant A (the default) which however may change.

### Incompatible subtypes

` `` My_Integer `` `` -10 .. + 10;`\
` `` My_Positive `` My_Integer `` + 1 .. + 10;`\
` `` My_Negative `` My_Integer `` -10 .. -  1;`

These subtypes are of course incompatible.

Another example are subtypes of a discriminated record:

` `` My_Enum `` (A, B, C);`\
` `` My_Record (Discriminant: My_Enum) `` ...;`\
` `` My_A_Record `` My_Record (A);`\
` `` My_C_Record `` My_Record (C);`

Also these subtypes are incompatible.

## Qualified expressions

In most cases, the compiler is able to infer the type of an expression;
for example:

` Enum `` (A, B, C);`\
`E : Enum := A;`

Here the compiler knows that `A` is a value of the type `Enum`. But
consider:

` Bad `\
`   `` Enum_1 `` (A, B, C);`\
`   `` P (E : `` Enum_1) ``... `\
`   `` Enum_2 `` (A, X, Y, Z);`\
`   `` P (E : `` Enum_2) ``... `\
\
`   P (A); `\
` Bad;`

The compiler cannot choose between the two versions of `P`; both would
be equally valid. To remove the ambiguity, you use a *qualified
expression*:

`   P (Enum_1'(A)); `

As seen in the following example, this syntax is often used when
creating new objects. If you try to compile the example, it will fail
with a compilation error since the compiler will determine that 256 is
not in range of `Byte`.

\
\
` ``;`\
\
` Convert_Evaluate_As `\
`   `` Byte     `` `` 2**8;`\
`   `` Byte_Ptr `` `` Byte;`\
\
`   `` T_IO `` ``;`\
`   `` M_IO `` `` `` (Byte);`\
\
`   A : `` Byte_Ptr := `` Byte'(256);`\
\
`   T_IO.Put ("A = ");`\
`   M_IO.Put (Item  => A.all,`\
`             Width =>  5,`\
`             Base  => 10);`\
` Convert_Evaluate_As;`

You should use qualified expression when getting a string literal\'s
length.

``` ada
"foo"'Length                  -- compilation error: prefix of attribute must be a name
                              --                    qualify expression to turn it into a name
String'("foo" & "bar")'Length -- 6
```

## Type conversions

Data do not always come in the format you need them. You must, then,
face the task of converting them. As a true multi-purpose language with
a special emphasis on \"mission critical\", \"system programming\" and
\"safety\", Ada has several conversion techniques. The most difficult
part is choosing the right one, so the following list is sorted in order
of utility. You should try the first one first; the last technique is a
last resort, to be used if all others fail. There are also a few related
techniques that you might choose instead of actually converting the
data.

Since the most important aspect is not the result of a successful
conversion, but how the system will react to an invalid conversion, all
examples also demonstrate **faulty** conversions.

### Explicit type conversion

An explicit type conversion looks much like a function call; it does not
use the *tick* (apostrophe, \') like the qualified expression does.

`Type_Name (`*`Expression`*`)`

The compiler first checks that the conversion is legal, and if it is, it
inserts a run-time check at the point of the conversion; hence the name
*checked conversion*. If the conversion fails, the program raises
Constraint_Error. Most compilers are very smart and optimise away the
constraint checks; so, you need not worry about any performance penalty.
Some compilers can also warn that a constraint check will always fail
(and optimise the check with an unconditional raise).

Explicit type conversions are legal:

-   between any two numeric types
-   between any two subtypes of the same type
-   between any two types derived from the same type (note special rules
    for tagged types)
-   between array types under certain conditions (see RM
    4.6(24.2/2..24.7/2))
-   and *nowhere else*

(The rules become more complex with class-wide and anonymous access
types.)

`I: Integer := Integer (10);  `\
`J: Integer := 10;            `\
`K: Integer := Integer'(10);  `\
`                             `

This example illustrates explicit type conversions:

\
\
` ``;`\
\
` Convert_Checked `\
`   `` Short `` `` -128 .. +127;`\
`   `` Byte  `` `` 256;`\
\
`   `` T_IO `` ``;`\
`   `` I_IO `` `` `` (Short);`\
`   `` M_IO `` `` `` (Byte);`\
\
`   A : Short := -1;`\
`   B : Byte;`\
\
`   B := Byte (A);  -- range check will lead to Constraint_Error`\
`   T_IO.Put ("A = ");`\
`   I_IO.Put (Item  =>  A,`\
`             Width =>  5,`\
`             Base  => 10);`\
`   T_IO.Put (", B = ");`\
`   M_IO.Put (Item  =>  B,`\
`             Width =>  5,`\
`             Base  => 10);`\
` Convert_Checked;`

Explicit conversions are possible between any two numeric types:
integers, fixed-point and floating-point types. If one of the types
involved is a fixed-point or floating-point type, the compiler not only
checks for the range constraints (thus the code above will raise
Constraint_Error), but also performs any loss of precision necessary.

Example 1: the loss of precision causes the procedure to only ever print
\"0\" or \"1\", since `P / 100` is an integer and is always zero or one.

` Ada.Text_IO;`\
` Naive_Explicit_Conversion `\
`   `` Proportion `` `` 4 `` 0.0 .. 1.0;`\
`   `` Percentage `` `` 0 .. 100;`\
`   `` To_Proportion (P : `` Percentage) `` Proportion `\
`   `\
`      `` Proportion (P / 100);`\
`   `` To_Proportion;`\
\
`   Ada.Text_IO.Put_Line (Proportion'Image (To_Proportion (27)));`\
` Naive_Explicit_Conversion;`

Example 2: we use an intermediate floating-point type to guarantee the
precision.

` Ada.Text_IO;`\
` Explicit_Conversion `\
`   `` Proportion `` `` 4 `` 0.0 .. 1.0;`\
`   `` Percentage `` `` 0 .. 100;`\
`   `` To_Proportion (P : `` Percentage) `` Proportion `\
`      `` Prop `` `` 4 `` 0.0 .. 100.0;`\
`   `\
`      `` Proportion (Prop (P) / 100.0);`\
`   `` To_Proportion;`\
\
`   Ada.Text_IO.Put_Line (Proportion'Image (To_Proportion (27)));`\
` Explicit_Conversion;`

You might ask why you should convert between two subtypes of the same
type. An example will illustrate this.

` String_10 `` String (1 .. 10);`\
`X: String := "A line long enough to make the example valid";`\
`Slice: `` String := String_10 (X (11 .. 20));`

Here, `Slice` has bounds 1 and 10, whereas `X (11 .. 20)` has bounds 11
and 20.

### Change of Representation

Type conversions can be used for packing and unpacking of records or
arrays.

` Unpacked `` `\
`  `\
` ``;`\
\
` Packed `` `` Unpacked;`\
`  Packed `` `\
`  `\
` ``;`

`P: Packed;`\
`U: Unpacked;`\
\
`P := Packed (U);  `\
`U := Unpacked (P);  `

### Checked conversion for non-numeric types

The examples above all revolved around conversions between numeric
types; it is possible to convert between any two numeric types in this
way. But what happens between non-numeric types, e.g. between array
types or record types? The answer is two-fold:

-   you can convert explicitly between a type and types derived from it,
    or between types derived from the same type,
-   and that\'s all. No other conversions are possible.

Why would you want to derive a record type from another record type?
Because of representation clauses. Here we enter the realm of low-level
systems programming, which is not for the faint of heart, nor is it
useful for desktop applications. So hold on tight, and let\'s dive in.

Suppose you have a record type which uses the default, efficient
representation. Now you want to write this record to a device, which
uses a special record format. This special representation is more
compact (uses fewer bits), but is grossly inefficient. You want to have
a layered programming interface: the upper layer, intended for
applications, uses the efficient representation. The lower layer is a
device driver that accesses the hardware directly and uses the
inefficient representation.

` Device_Driver `\
`   `` Size_Type `` `` 0 .. 64;`\
`   `` Register `` `\
`      A, B : Boolean;`\
`      Size : Size_Type;`\
`   `` ``;`\
\
`   `` Read (R : `` Register);`\
`   `` Write (R : `` Register);`\
` Device_Driver;`

The compiler chooses a default, efficient representation for `Register`.
For example, on a 32-bit machine, it would probably use three 32-bit
words, one for A, one for B and one for Size. This efficient
representation is good for applications, but at one point we want to
convert the entire record to just 8 bits, because that\'s what our
hardware requires.

` `` Device_Driver `\
`   `` Hardware_Register `` `` Register; `\
`   `` Hardware_Register `` `\
`      A `` 0 `` 0 .. 0;`\
`      B `` 0 `` 1 .. 1;`\
`      Size `` 0 `` 2 .. 7;`\
`   `` ``;`\
\
`   `` Get `` Hardware_Register; `\
`   `` Put (H : `` Hardware_Register); `\
\
`   `` Read (R : `` Register) `\
`      H : Hardware_Register := Get;`\
`   `\
`      R := Register (H); `\
`   `` Read;`\
\
`   `` Write (R : `` Register) `\
`   `\
`      Put (Hardware_Register (R)); `\
`   `` Write;`\
` Device_Driver;`

In the above example, the package body declares a derived type with the
inefficient, but compact representation, and converts to and from it.

This illustrates that **type conversions can result in a change of
representation**.

### View conversion, in object-oriented programming

Within object-oriented
programming you have to
distinguish between *specific* types and *class-wide* types.

With specific types, only conversions in the direction to the root are
possible, which of course cannot fail. There are no conversions in the
opposite direction `<small>`{=html}(where would you get the further
components from?)`</small>`{=html}; *extension aggregates* have to be
used instead.

With the conversion itself, no components of the source object that are
not present in the target object are lost, they are just hidden from
visibility. Therefore, this kind of conversion is called a *view
conversion* since it provides a view of the source object as an object
of the target type (especially it does not change the object\'s tag).

It is a common idiom in object oriented programming to rename the result
of a view conversion. (A renaming declaration does not create a new
object; it only gives a new name to something that already exists.)

` Parent_Type `` `` `\
`   ``<components>`{=html}`;`\
` ``;`\
` Child_Type `` `` Parent_Type `` `\
`   ``<further components>`{=html}`;`\
` ``;`\
\
`Child_Instance : Child_Type;`\
`Parent_View    : Parent_Type `` Parent_Type (Child_Instance);`\
`Parent_Part    : Parent_Type := Parent_Type (Child_Instance);`

`Parent_View` is not a new object, but another name for `Child_Instance`
viewed as the parent, i.e. only the parent components are visible, the
child-specific components are hidden. `Parent_Part`, however, is an
object of the parent type, which of course has no storage for the
child-specific components, so they are lost with the assignment.

All types derived from a tagged type `T` form a tree rooted at `T`. The
class-wide type `T'Class` can hold any object within this tree. With
class-wide types, conversions in any direction are possible; there is a
run-time tag check that raises `Constraint_Error` if the check fails.
These conversions are also view conversions, no data is created or lost.

`Object_1 : Parent_Type'`` := Parent_Type'`` (Child_Instance);`\
`Object_2 : Parent_Type'`` `` Parent_Type'`` (Child_Instance);`

`Object_1` is a new object, a copy; `Object_2` is just a new name. Both
objects are of the class-wide type. Conversions to any type within the
given class are legal, but are tag-checked.

`Success : Child_Type := Child_Type (Parent_Type'Class (Parent_View));`\
`Failure : Child_Type := Child_Type (Parent_Type'Class (Parent_Part));`

The first conversion passes the tag check and both objects
`Child_Instance` and `Success` are equal. The second conversion fails
the tag check. `<small>`{=html}(Conversion assignments of this kind will
rarely be used; dispatching will do this automatically, see object
oriented
programming.)`</small>`{=html}

You can perform these checks yourself with membership tests:

` Parent_View `` Child_Type `` ...`\
` Parent_View `` Child_Type'`` `` ...`

There is also the package `Ada.Tags`.

### Address conversion

Ada\'s access type is not
just a memory location (a thin pointer). Depending on implementation and
the access type used, the
access might keep additional
information (a fat pointer). For example GNAT keeps two memory addresses
for each access to an
indefinite object --- one for the data and one for the constraint
informations `<small>`{=html}(,
,
\'\')`</small>`{=html}.

If you want to convert an access to a simple memory location you can use
the package
. Note
however that an address and a fat pointer cannot be converted reversibly
into one another.

The address of an array object is the address of its first component.
Thus the bounds get lost in such a conversion.

` My_Array `` `` (Positive `` <>) `` Something;`\
`A: My_Array (50 .. 100);`\
\
`     A'`` = A(A'``)'`

### Unchecked conversion

One of the great criticisms of Pascal was \"there is no escape\". The
reason was that sometimes you have to convert the incompatible. For this
purpose, Ada has the generic function *Unchecked_Conversion*:

\
`   `` Source (<>) `` `` ``;`\
`   `` Target (<>) `` `` ``;`\
` `` (S : Source) `` Target;`

*`Unchecked_Conversion`* will bit-copy the source data and reinterpret
them under the target type without any checks. It is **your** chore to
make sure that the requirements on unchecked conversion as stated in RM
 are fulfilled; if not, the result is
implementation dependent and may even lead to abnormal data. Use the
\'Valid attribute after the conversion to check the validity of the data
in problematic cases.

A function call to (an instance of) `Unchecked_Conversion` will copy the
source to the destination. The compiler may also do a conversion *in
place* (every instance has the convention *Intrinsic*).

To use `Unchecked_Conversion` you need to instantiate the generic.

In the example below, you can see how this is done. When run, the
example will output `A = -1, B = 255`. No error will be reported, but is
this the result you expect?

\
\
` ``;`\
` ``;`\
\
` Convert_Unchecked `\
\
`   `` Short `` `` -128 .. +127;`\
`   `` Byte  `` `` 256;`\
\
`   `` T_IO `` ``;`\
`   `` I_IO `` `` `` (Short);`\
`   `` M_IO `` `` `` (Byte);`\
\
`   `` Convert `` `` `` (Source => Short,`\
`                                                     Target => Byte);`\
\
`   A : `` Short := -1;`\
`   B : Byte;`\
\
\
\
`   B := Convert (A);`\
`   T_IO.Put ("A = ");`\
`   I_IO.Put (Item  =>  A,`\
`             Width =>  5,`\
`             Base  => 10);`\
`   T_IO.Put (", B = ");`\
`   M_IO.Put (Item  =>  B,`\
`             Width =>  5,`\
`             Base  => 10);`\
\
` Convert_Unchecked;`

There is of course a range check in the assignment `B := Convert (A);`.
Thus if `B` were defined as
`B: Byte `` 0 .. 10;`, `Constraint_Error`
would be raised.

### Overlays

If the copying of the result of `Unchecked_Conversion` is too much waste
in terms of performance, then you can try overlays, i.e. address
mappings. By using overlays, both objects share the same memory
location. If you assign a value to one, the other changes as well. The
syntax is:

` Target'`` `` `*`expression`*`;`\
` (Ada, Target);`

where *expression* defines the address of the source object.

While overlays might look more elegant than `Unchecked_Conversion`, you
should be aware that they are even more dangerous and have even greater
potential for doing something very wrong. For example if
`Source'`` < Target'`
and you assign a value to Target, you might inadvertently write into
memory allocated to a different object.

You have to take care also of implicit initializations of objects of the
target type, since they would overwrite the actual value of the source
object. The Import pragma with convention Ada can be used to prevent
this, since it avoids the implicit initialization, RM
.

The example below does the same as the example from \"Unchecked
Conversion\".

\
\
` ``;`\
\
` Convert_Address_Mapping `\
`   `` Short `` `` -128 .. +127;`\
`   `` Byte  `` `` 256;`\
\
`   `` T_IO `` ``;`\
`   `` I_IO `` `` `` (Short);`\
`   `` M_IO `` `` `` (Byte);`\
\
`   A : `` Short;`\
`   B : `` Byte;`\
`  `\
`   `` B'`` `` A'``;`\
`  `` (Ada, B);`\
`  `\
\
`   A := -1;`\
`   T_IO.Put ("A = ");`\
`   I_IO.Put (Item  =>  A,`\
`             Width =>  5,`\
`             Base  => 10);`\
`   T_IO.Put (", B = ");`\
`   M_IO.Put (Item  =>  B,`\
`             Width =>  5,`\
`             Base  => 10);`\
` Convert_Address_Mapping;`

### Export / Import

Just for the record: There is still another method using the
 and
 pragmas. However, since this
method completely undermines Ada\'s visibility and type concepts even
more than overlays, it has no place here in this language introduction
and is left to experts.

## Elaborated Discussion of Types for Signed Integer Types

As explained before, a type declaration

` T `` `` 1 .. 10;`

declares an anonymous type *`T`* and its first subtype `T` (please note
the italicization). *`T`* encompasses the complete set of mathematical
integers. Static expressions and named numbers make use of this fact.

All numeric integer literals are of type `Universal_Integer`. They are
converted to the appropriate specific type where needed.
`Universal_Integer` itself has no operators.

Some examples with static named numbers:

` S1: `` := Integer'`` + Integer'``;       `\
` S2: `` := Long_Integer'`` + 1;             `\
` S3: `` := S1 + S2;                           `\
` S4: `` := Integer'`` + Long_Integer'``;  `

Static expressions are evaluated at compile-time on the appropriate
types with no overflow checks, i.e. mathematically exact (only limited
by computer store). The result is then implicitly converted to
`Universal_Integer`.

The literal 1 in `S2` is of type `Universal_Integer` and implicitly
converted to `Long_Integer`.

`S3` implicitly converts the summands to `root_integer`, performs the
calculation and converts back to `Universal_Integer`.

`S4` is illegal because it mixes two different types. You can however
write this as

` S5: `` := Integer'Pos (Integer'``) + Long_Integer'Pos (Long_Integer'``);  `

where the Pos attributes convert the values to `Universal_Integer`,
which are then further implicitly converted to `root_integer`, added and
the result converted back to `Universal_Integer`.

`root_integer` is the anonymous greatest integer type representable by
the hardware. It has the range
`System.Min_Integer .. System.Max_Integer`. All integer types are rooted
at `root_integer`, i.e. derived from it. `Universal_Integer` can be
viewed as `root_integer'Class`.

During run-time, computations of course are performed with range checks
and overflow checks on the appropriate subtype. Intermediate results may
however exceed the range limits. Thus with `I, J, K` of the subtype `T`
above, the following code will return the correct result:

`I := 10;`\
`J :=  8;`\
`K := (I + J) - 12;`\

Real literals are of type `Universal_Real`, and similar rules as the
ones above apply accordingly.

## Relations between types

Types can be made from other types. Array types, for example, are made
from two types, one for the arrays\' index and one for the arrays\'
components. An array, then, expresses an association, namely that
between one value of the index type and a value of the component type.

` `` Color `` (Red, Green, Blue);`\
` `` Intensity `` `` 0 .. 255;`\
` `\
` `` Colored_Point `` `` (Color) `` Intensity;`

The type `Color` is the index type and the type `Intensity` is the
component type of the array type `Colored_Point`. See
array.

## See also

### Wikibook

-   Ada Programming

### Ada Reference Manual

-
-
-
-
-
-
-
-
System es:Programación en
Ada/Tipos


# Ada Programming/Constants

# Are Constants Constant?

Variables and constants are declared like so:

`X, Y: T := Some_Value;  -- Initialization optional`\
`C: `` T := Some_Value;`

The initialization value for X and Y is evaluated separately for each
one -- thus, if this is a function call, they may have different values.

For the nomenclature: Ada calls variables and constants together
\"objects\". Do not confuse this with the term \"objects\" used in OOP.

It is good practice to declare local objects which do not change as
constant.

Silly question: What actually does \"constant\" mean?

` Swap (X, Y: `` T) `\
`  Temp: `` T := X;`\
\
`  X := Y;`\
`  Y := Temp;`\
` Swap;`

In the Swap example, the temporary copy of X certainly is constant -- we
do not touch it. However (a triviality you'll say), it is not constant
during construction nor during destruction at the end of Swap.

Hold it!

In the following, you will learn some astonishing facts about
"constants" (objects with the keyword constant).

## First Doubts

Let us sow first doubts about the constancy.

Controlled types (RM 7.6) grant the programmer access to the process of
construction, copy and destruction via the three operations Initialize,
Adjust and Finalize.

Given a controlled type T.

`X: `` T := F;`

After construction of X and its initialization with a copy of F, the
operation Adjust is called with parameter mode in out for the constant
object X. (Initialize is not called here because an initial value is
given.)

In Ada.\*\_IO (RM A.6-A.10), the file parameter of Create and Close has
mode in out, of Read and Write (resp. Put and Get) it has in. But each
of these operations does change the state of the file parameter.

This reflects a design where the (internal) File object\'s \"state\"
represents the open-ness of the File object, rather than the content of
the (external) file. Agreed that this choice is debatable, but it is
consistent across the I/O packages.

The presumed implementation model implies a level of indirection, where
the File parameter represents a reference, which is essentially \"null\"
when the file is closed, and non-null when the file is open. Everything
else is buried in some mysterious netherland whose state is not
reflected in the mode of the File parameter.

This is a symptom of any language that has pointer parameters whose mode
has no effect on the ability to update the pointed-to object.

So:

**An object is not constant at least during construction and
destruction.**

But as you have seen with Ada.\*\_IO, a constant object can indeed
change its state also during its lifetime. (An in parameter is like a
constant within a subprogram.)

**"The constant keyword means that the value never changes" -- this is a
False statement for Ada** (the details are painful); it\'s true for
elementary types and some others, but not for most composite types.

You can find some interesting statements about this in Ada RM: RM
3.3(13/3, 25.1/3), 13.9.1(13/3). The corresponding terms are *immutably
limited* and *inherently mutable*.

## Example Pointers

`Pointer:`\
\
`  `` Rec `` `\
`    I: `` Integer;`\
`  `` ``;`\
`  Ob: `` Rec := (I => `` Integer'(42));`\
`  -- Ob.I is constant, but not Ob.I.all!`\
\
`  Ob.I.all := 53;`\
` Pointer;`

Here you will certainly agree with me that this is clear as daylight.

But what about the case of an internal pointer accessing the whole
object itself?

`Reflexive:`\
\
`  `` Rec `` `` ``  -- immutably limited`\
`    -- Rosen technique (only possible on immutably limited types);`\
`    -- Ref is a variable view (Rec is aliased since it is limited).`\
`    Ref: `` Rec := Rec'Unchecked_Access;`\
`    I  : Integer;`\
`  `` ``;`\
`  Ob: `` Rec := (I => 42, Ref => <>);`\
\
`  Ob.I := 53;  -- illegal`\
`  Ob.Ref.I := 53;  -- erroneous until Ada 2005, legal for Ada 2012`\
` Reflexive;`

The object must be limited since copying would ruin the reference.

Ada 2012 AARM 13.9.1(14.e/3): The Rosen trick (named after Jean Pierre
Rosen) is no longer erroneous when the actual object is constant, but
good practice.

This applies to objects where there is necessarily a variable view at
some point in the lifetime of the object which you can \"squirrel away\"
for later use. This certainly does not happen \"by mistake\", the
programmer does it on purpose.

` Controlled `\
`  `` Rec `` `` Ada.Finalization.Controlled `` `\
`    Ref: `` Rec;  -- variable view`\
`    I  : Integer;`\
`  `` ``;`\
`  `` `` Initialize (T: `` Rec);`\
`  `` `` Adjust     (T: `` Rec);`\
`  -- "in out" means they see a variable view of the object`\
`  -- (even if it's a constant)`\
` Controlled;`

You can use it like so:

\
`  `` Create `` Controlled.Rec `` … `` Create;`\
`  Ob: `` Controlled.Rec := Create;`\
`  -- here, Adjust works on a constant on an assignment operation`\
\
`  Ob.Ref.I := 53;  -- Ob.I := 53;  illegal`\
`;`

A copy of the return object Create is assigned to Ob, the object Create
is finalized. Now the component Ref points to a no longer existing
object. (Note the difference between *assignment statement* and
*assignment operation*.) Adjust has to correct the wrong target.

Create might look like this:

` Create `` Controlled.Rec `\
`  X: Controlled.Rec;  -- Initialize called`\
\
`  `` X;`\
` Create;`

The variable X is declared without an initial value, so Initialize is
called. Create returns this self referencing object.

This is the package body:

` `` Controlled `\
`  `` Initialize (T: `` Rec) `\
`  `\
`    T := (Ada.Finalization.Controlled `\
`          Ref => T'Unchecked_Access,`\
`          I   => 42);`\
`  `` Initialize;`\
`  `` Adjust (T: `` Rec) `\
`  `\
`    T.Ref := T'Unchecked_Access;`\
`  `` Adjust;`\
` Controlled;`

Initiallize is only called if no initial value is given in the object
declaration. T is regarded as *aliased* so that the component Ref is a
variable view of the object itself.

## Example Task and Protected Object

Tasks are active objects, i.e. each task has its own thread of control:
All tasks run concurrently. A task communicates with other tasks via
rendezvous by calling one of its entries (roughly corresponding to a
subprogram call).

Since Ada is a block-oriented language, tasks may be defined as
components of arrays and records, and these may be constants.

` `` TT `\
`  `` Set (I: Integer);`\
` TT;`\
` `` TT ``      -- local objects are not`\
`  I: Integer := 42;  -- considered part of constant`\
\
`  `` Set (I: Integer) `\
`    TT.I := I;`\
`  `` Set;`\
` TT;`\
` Rec `` `\
`  T: TT;  -- active object that changes state (even if "constant")`\
` record;`\
`Ob: `` Rec := (T => <>);`

`Ob.T.Set (53);  -- execution of an entry of a constant task`

Protected objects are very similar to tasks.

` `` Prot `\
`  `` Set (I: Integer);`\
\
`  I: Integer := 42;  -- *`\
` Prot;`\
` `` Prot `\
`  `` Set (I: Integer) `\
`  `\
`    Prot.I := I;  -- Prot.I is *`\
`  `` Set;`\
` Prot;`\
` Rec `` `` `\
`  Ref: `` Rec := Rec'Unchecked_Access;  -- reflexive`\
`  P  : Prot;`\
` ``;`\
`Ob: `` Rec := (`` => <>);`

`Ob.P.Set (53);      -- illegal`\
`Ob.Ref.P.Set (53);  -- variable view required`

## Constants Are Like This

If an object is declared "constant", the meaning is just twofold:

-   The object cannot be used in an assignment (if it is not yet
    limited).
-   The object can only be used as an in parameter.

**In no case at all does it mean that the logical state of the object is
immutable.** In fact, such a type should be
_private_, which means _the client has
no influence at all on what happens in the object's inside. The provider
is responsible for the correct behavior._ *Immutably
limited* and *controlled objects* are *inherently mutable*.

# See also

## Wikibook

-   Ada
    Programming/Keywords/constant

## Ada Reference Manual

-
-
Programming}}\|Constants es:Programación en
Ada/Objetos


# Ada Programming/Representation clauses

There are several forms to specify the representation of items.

## Attributes

` Day_Of_Month `` `` 1 .. 31;`\
`  Day_Of_Month'``      `` 8;  `\
`  Day_Of_Month'`` `` 1;  `

## Records

A record representation clause specifies the *Layout*
aspect of a record. For any
component, a *component clause* may be given specifying the location
within the record object by its storage unit offset with respect to the
address (called *Position*) and the bits occupied at this position
(called *First_Bit* and *Last_Bit*):

`Component_Name `` Position `` First_Bit .. Last_Bit;`

These three expressions must be static, not negative and of any integer
type; they have corresponding
attributes **\'Position**,
**\'First_Bit** and **\'Last_Bit**. Note that the bit range may extend
well over storage unit boundaries. Components without a component clause
are located at the compiler\'s choice.

Example:

` Device_Register `` `\
`   Ready : Status_Flag;`\
`   Error : Error_Flag;`\
`   Data  : Unsigned_16;`\
` ``;`\
\
`  Device_Register `` `\
`   Ready `` 0 ``  0 ..  0;`\
`   Error `` 0 ``  1 ..  1;`\
`   `\
`   Data  `` 0 `` 16 .. 31;`\
` ``;`

Alternatively with identical result:

`  Device_Register `` `\
`   Ready `` 0 `` 0 ..  0;`\
`   Error `` 0 `` 1 ..  1;`\
`   `\
`   Data  `` 1 `` 0 .. 15;`\
` ``;`

The layout depends of course on whether the machine architecture is
*little endian* or *big endian*. The corresponding
attribute is called
\'Bit_Order.

For the Data component in the native bit order, **\'Position**,
**\'First_Bit** and **\'Last_Bit** will in both cases return 1, 0 and
15.

### Biased Representation

For certain components, a so-called *biased representation* may be
possible. For the type T, the attribute
\'Size will return 10,
but since it has only eight values, three bits would suffice. This can
be forced with the following specification:

` T `` `` 1000 .. 1007;`

` Rec `` `\
`   A: Integer `` 0 .. 1;`\
`   B: Boolean;`\
`   C: T;`\
` ``;`

` Rec `` `\
`   B `` 0 `` 0 .. 1;`\
`   C `` 0 `` 4 .. 6;  `\
` ``;`

Note that no size clause is needed for type T. Thus, a *change of
representation* is performed in either way when record components and
stand-alone objects of type T are assigned to one another.

Also note that for component `A` the compiler is free to choose any of
the remaining bits of position 0, but may also use at position 1 as many
bits as an integer requires in the given implementation.

## Enumerations

An enumeration representation clause specifies the *Coding*
aspect of an enumeration type with
a named aggregate.

` Status_Flag ``  (Ready, Wait);`\
`  Status_Flag `` (Ready => 0, Wait => 1);  `

Another representation:

`  Status_Flag `` (Ready => 0, Wait => 2#100#);`

The expressions for the literals must be static and of any integer type.
The values must not conflict with the order.

## The Aspect Pack

The aspect Pack may be used for
arrays and records. It specifies that for each component as many bits
are used as the attribute
\'Size applied to its
subtype returns.


# Ada Programming/Strings

Ada supports three different types of strings. Each string type is
designed to solve a different problem.

In addition, every string type is implemented for each available
Characters type `<small>`{=html}(Character, Wide_Character,
Wide_Wide_Character)`</small>`{=html} giving a complement of nine
combinations.

## Fixed-length string handling

Fixed-Length Strings (the predefined type
String) are
arrays of Character, and
consequently of a fixed length. Since String is an indefinite
subtype the
length does not need to be known at compile time --- the length may well
be calculated at run time. In the following example the length is
calculated from command-line argument 1:

`X : String := Ada.Command_Line.Argument (1);`

However once the length has been calculated and the string has been
created the length stays constant. Try the following program which shows
a typical mistake:

\
\
` ``;`\
` ``;`\
\
` Show_Commandline_1 `\
\
`   `` T_IO `` ``;`\
`   `` CL   `` ``;`\
\
`   X : String := CL.Argument (1);`\
\
\
`   T_IO.Put ("Argument 1 = ");`\
`   T_IO.Put_Line (X);`\
\
`   X := CL.Argument (2);`\
\
`   T_IO.Put ("Argument 2 = ");`\
`   T_IO.Put_Line (X);`\
` Show_Commandline_1;`

The program will only work when the 1st and 2nd parameter have the same
length. This is even true when the 2nd parameter is shorter. There is
neither an automatic padding of shorter strings nor an automatic
truncation of longer strings.

Having said that, the package
 contains a set of
procedures and functions for Fixed-Length String Handling which allows
padding of shorter strings and truncation of longer strings.

Try the following example to see how it works:

` ``;`\
` ``;`\
` ``;`\
\
` Show_Commandline_2 `\
\
`   `` T_IO `` ``;`\
`   `` CL   `` ``;`\
`   `` S    `` ``;`\
`   `` SF   `` ``;`\
\
`   X : String := CL.Argument (1);`\
\
\
`   T_IO.Put ("Argument 1 = ");`\
`   T_IO.Put_Line (X);`\
\
`   SF.Move (`\
`     Source  => CL.Argument (2),`\
`     Target  => X,`\
`     Drop    => S.Right,`\
`     Justify => S.Left,`\
`     Pad     => S.Space);`\
\
`   T_IO.Put ("Argument 2 = ");`\
`   T_IO.Put_Line (X);`\
` Show_Commandline_2;`

## Bounded-length string handling

Bounded-Length Strings can be used when the maximum length of a string
is known and/or restricted. This is often the case in database
applications where only a limited number of characters can be stored.

Like Fixed-Length Strings the maximum length does not need to be known
at compile time --- it can also be calculated at runtime --- as the
example below shows:

\
\
` ``;`\
` ``;`\
` ``;`\
\
` Show_Commandline_3 `\
\
`   `` T_IO `` Ada.Text_IO;`\
`   `` CL   `` Ada.Command_Line;`\
\
`   `` Max_Length (`\
`      Value_1 : Integer;`\
`      Value_2 : Integer)`\
`   `\
`      Integer`\
`   `\
`      Retval : Integer;`\
`   `\
`      `` Value_1 > Value_2 `\
`         Retval := Value_1;`\
`      `\
`         Retval := Value_2;`\
`      `` ``;`\
`      `` Retval;`\
`   `` Max_Length;`\
\
`   `` Inline (Max_Length);`\
\
`   `` SB`\
`   `` `` Ada.Strings.Bounded.Generic_Bounded_Length (`\
`       Max => Max_Length (`\
`                  Value_1 => CL.Argument (1)'Length,`\
`                  Value_2 => CL.Argument (2)'Length));`\
\
`   X :  SB.Bounded_String`\
`     := SB.To_Bounded_String (CL.Argument (1));`\
\
\
`   T_IO.Put ("Argument 1 = ");`\
`   T_IO.Put_Line (SB.To_String (X));`\
\
`   X := SB.To_Bounded_String (CL.Argument (2));`\
\
`   T_IO.Put ("Argument 2 = ");`\
`   T_IO.Put_Line (SB.To_String (X));`\
` Show_Commandline_3;`

You should know that Bounded-Length Strings have some distinct
disadvantages. Most noticeable is that each Bounded-Length String is a
different type which makes converting them rather cumbersome. Also a
Bounded-Length String type always allocates memory for the maximum
permitted string length for the type. The memory allocation for a
Bounded-Length String is equal to the maximum number of string
\"characters\" plus an implementation dependent number containing the
string length (each character can require allocation of more than one
byte per character, depending on the underlying character type of the
string, and the length number is 4 bytes long for the Windows GNAT Ada
compiler v3.15p, for example).

## Unbounded-length string handling

Last but not least there is the Unbounded-Length String. In fact: If you
are not doing embedded or database programming this will be the string
type you are going to use most often as it gives you the maximum amount
of flexibility.

As the name suggest the Unbounded-Length String can hold strings of
almost any length --- limited only to the value of Integer\'Last or your
available heap memory. This is because Unbounded_String type is
implemented using dynamic memory allocation behind the scenes, providing
lower efficiency but maximum flexibility.

` ``;`\
` ``;`\
` ``;`\
\
` Show_Commandline_4 `\
\
`   `` T_IO `` Ada.Text_IO;`\
`   `` CL   `` Ada.Command_Line;`\
`   `` SU   `` Ada.Strings.Unbounded;`\
\
`   X :  SU.Unbounded_String `\
`     := SU.To_Unbounded_String (CL.Argument (1));`\
\
\
`   T_IO.Put ("Argument 1 = ");`\
`   T_IO.Put_Line (SU.To_String (X));`\
\
`   X := SU.To_Unbounded_String (CL.Argument (2));`\
\
`   T_IO.Put ("Argument 2 = ");`\
`   T_IO.Put_Line (SU.To_String (X));`\
` Show_Commandline_4;`

As you can see the Unbounded-Length String example is also the shortest
`<small>`{=html}(disregarding the buggy first example)`</small>`{=html}
--- this makes using Unbounded-Length Strings very appealing.

## See also

### Wikibook

-   Ada Programming

### Ada 95 Reference Manual

-
-
-
-
-
### Ada 2005 Reference Manual

-
-
-
-
-
Programming}}\|Strings

es:Programación en
Ada/Tipos/Strings


# Ada Programming/Subprograms

In Ada the subprograms are classified into two categories:
procedures and
functions. A procedures call is a statement and
does not return any value, whereas a function returns a value and must
therefore be a part of an expression.

Subprogram parameters may have three modes.

: The actual parameter value goes into the call and is not changed there; the formal parameter is a constant and allows only reading -- with a caveat, see Ada Programming/Constants. This is the default when no mode is given. The actual parameter can be an expression.\
 : The actual parameter goes into the call and may be redefined. The formal parameter is a variable and can be read and written.\
: The actual parameter\'s value before the call is irrelevant, it will get a value in the call. The formal parameter can be read and written. (In Ada 83  parameters were write-only.)

A parameter of any mode may also be explicitly
.

: The formal parameter is an access (a pointer) to some variable. (This is not a parameter mode from the reference manual point of view.)

Note that parameter modes do not specify the parameter passing method.
Their purpose is to document the data flow.

The parameter passing method depends on the type of the parameter. A
rule of thumb is that parameters fitting into a register are passed by
copy, others are passed by reference. For certain types, there are
special rules, for others the parameter passing mode is left to the
compiler (which you can assume to do what is most sensible). Tagged
types are always passed by reference.

Explicitly  parameters and
 parameters specify pass by reference.

Unlike in the C class of programming languages, Ada subprogram calls
cannot have empty parameters parentheses
` ` when there are
no parameters.

## Procedures

A procedure call in Ada constitutes a statement by itself.

For example:

` A_Test ``A, B: `` Integer; C: `` Integer`` `\
\
`   C := A + B;`\
` A_Test;`

When the procedure is called with the statement

`A_Test (5 + P, 48, Q);`

the expressions 5 + P and 48 are evaluated (expressions are only allowed
for in parameters), and then assigned to the formal parameters A and B,
which behave like constants. Then, the value A + B is assigned to formal
variable C, whose value will be assigned to the actual parameter Q when
the procedure finishes.

C, being an  parameter, is an uninitialized
variable before the first assignment. (Therefore in Ada 83, there
existed the restriction that  parameters are
write-only. If you wanted to read the value written, you had to declare
a local variable, do all calculations with it, and finally assign it to
C before return. This was awkward and error prone so the restriction was
removed in Ada 95.)

Within a procedure, the return statement can be used without arguments
to exit the procedure and return the control to the caller.

For example, to solve an equation of the kind $ax^2 + bx + c = 0$:

` ``;`\
`  ``;`\
\
` Quadratic_Equation`\
`   ``A, B, C :     Float;   `\
`    R1, R2  : `` Float;`\
`    Valid   : `` Boolean`\
\
`   Z : Float;`\
\
`   Z := B**2 - 4.0 * A * C;`\
`   `` Z < 0.0 `` A = 0.0 `\
`      Valid := False;  `\
`      R1    := 0.0;`\
`      R2    := 0.0;`\
`   `\
`      Valid := True;`\
`      R1    := (-B + Sqrt (Z)) / (2.0 * A);`\
`      R2    := (-B - Sqrt (Z)) / (2.0 * A);`\
`   `` ``;`\
` Quadratic_Equation;`

The function SQRT calculates the square root of non-negative values. If
the roots are real, they are given back in R1 and R2, but if they are
complex or the equation degenerates (A = 0), the execution of the
procedure finishes after assigning to the Valid variable the False
value, so that it is controlled after the call to the procedure. Notice
that the  parameters should be modified at
least once, and that if a mode is not specified, it is implied
.

## Functions

A function is a subprogram that can be invoked as part of an expression.
Until Ada 2005, functions can only take  (the
default) or  parameters; the latter can
be used as a work-around for the restriction that functions may not have
 parameters. Ada 2012 has removed this
restriction.

Here is an example of a function body:

` Minimum (A, B: Integer) `` Integer `\
\
`   `` A <= B `\
`      `` A;`\
`   `\
`      `` B;`\
`   `` ``;`\
` Minimum;`

(There is, by the way, also the attribute `Integer'Min`, see RM 3.5.) Or
in Ada2012:

` Minimum (A, B: Integer) `` Integer `\
\
`   `` (`` A <= B `` A `` B);`\
` Minimum;`

or even shorter as an *expression function*

` Minimum (A, B: Integer) `` Integer `` (`` A <= B `` A `` B);`

The formal parameters with mode  behave as
local constants whose values are provided by the corresponding actual
parameters. The statement  is used to
indicate the value returned by the function call and to give back the
control to the expression that called the function. The expression of
the  statement may be of arbitrary
complexity and must be of the same type declared in the specification.
If an incompatible type is used, the compiler gives an error. If the
restrictions of a subtype are not fulfilled, e.g. a range, it raises a
Constraint_Error exception.

The body of the function can contain several
 statements and the execution of any of
them will finish the function, returning control to the caller. If the
flow of control within the function branches in several ways, it is
necessary to make sure that each one of them is finished with a
 statement. If at run time the end of a
function is reached without encountering a
 statement, the exception Program_Error
is raised. Therefore, the body of a function must have at least one such
 statement.

Every call to a function produces a new copy of any object declared
within it. When the function finalizes, its objects disappear.
Therefore, it is possible to call the function recursively. For example,
consider this implementation of the factorial function:

` Factorial (N : Positive) `` Positive `\
\
`   `` N = 1 `\
`      `` 1;`\
`   `\
`      `` (N * Factorial (N - 1));`\
`   `` ``;`\
` Factorial;`

When evaluating the expression `Factorial (4);` the function will be
called with parameter 4 and within the function it will try to evaluate
the expression `Factorial (3)`, calling itself as a function, but in
this case parameter N would be 3 (each call copies the parameters) and
so on until N = 1 is evaluated which will finalize the recursion and
then the expression will begin to be completed in the reverse order.

A formal parameter of a function can be of any type, including vectors
or records. Nevertheless, it cannot be an anonymous type, that is, its
type must be declared before, for example:

` Float_Vector `` `` (Positive `` <>) `` Float;`\
\
` Add_Components (V: Float_Vector) `` Float `\
`   Result : Float := 0.0;`\
\
`   `` I `` V'`` `\
`      Result := Result + V(I);`\
`   `` ``;`\
`   `` Result;`\
` Add_Components;`

In this example, the function can be used on a vector of arbitrary
dimension. Therefore, there are no static bounds in the parameters
passed to the functions. For example, it is possible to be used in the
following way:

`V4  : Float_Vector (1 .. 4) := (1.2, 3.4, 5.6, 7.8);`\
`Sum : Float;`\
\
`Sum := Add_Components (V4);`

In the same way, a function can also return a type whose bounds are not
known a priori. For example:

` Invert_Components (V : Float_Vector) `` Float_Vector `\
`   Result : Float_Vector(V'``);   `\
\
`   `` I `` V'`` `\
`      Result(I) := V (V'`` + V'`` - I);`\
`   `` ``;`\
`   `` Result;`\
` Invert_Components; `

The variable Result has the same bounds as V, so the returned vector
will always have the same dimension as the one passed as parameter.

A value returned by a function can be used without assigning it to a
variable, it can be referenced as an expression. For example,
`Invert_Components (V4) (1)`, where the first element of the vector
returned by the function would be obtained (in this case, the last
element of V4, i.e. 7.8).

## Named parameters

In subprogram calls, named parameter notation (i.e. the name of the
formal parameter followed of the symbol
and then the actual parameter) allows the rearrangement of the
parameters in the call. For example:

`Quadratic_Equation (Valid => OK, A => 1.0, B => 2.0, C => 3.0, R1 => P, R2 => Q);`\
`F := Factorial (N => (3 + I));`

This is especially useful to make clear which parameter is which.

`Phi := Arctan (A, B);`\
`Phi := Arctan (Y => A, X => B);`

The first call (from Ada.Numerics.Elementary_Functions) is not very
clear. One might easily confuse the parameters. The second call makes
the meaning clear without any ambiguity.

Another use is for calls with numeric literals:

`Ada.Float_Text_IO.Put_Line (X, 3, 2, 0);  -- ?`\
`Ada.Float_Text_IO.Put_Line (X, Fore => 3, Aft => 2, Exp => 0);  -- OK`

## Default parameters

On the other hand, formal parameters may have default values. They can,
therefore, be omitted in the subprogram call. For example:

` By_Default_Example (A, B: `` Integer := 0);`

can be called in these ways:

`By_Default_Example (5, 7);      `\
`By_Default_Example (5);         `\
`By_Default_Example;             `\
`By_Default_Example (B => 3);    `\
`By_Default_Example (1, B => 2); `

In the first statement, a \"regular call\" is used (with positional
association); the second also uses positional association but omits the
second parameter to use the default; in the third statement, all
parameters are by default; the fourth statement uses named association
to omit the first parameter; finally, the fifth statement uses mixed
association, here the positional parameters have to precede the named
ones.

Note that the default expression is evaluated once for each formal
parameter that has no actual parameter. Thus, if in the above example a
function would be used as defaults for A and B, the function would be
evaluated once in case 2 and 4; twice in case 3, so A and B could have
different values; in the others cases, it would not be evaluated.

## Renaming

Subprograms may be renamed. The parameter and result profile for a
renaming-as-declaration must be mode conformant.

` Solve`\
`  (A, B, C: ``  Float;`\
`   R1, R2 : `` Float;`\
`   Valid  : `` Boolean) `` Quadratic_Equation;`

This may be especially comfortable for tagged types.

` Some_Package `\
`  `` Message_Type `` `` `` ``;`\
`  `` Print (Message: `` Message_Type);`\
` Some_Package; `

` Some_Package;`\
` Main `\
`  Message: Some_Package.Message_Type;`\
`  `` Print `` Message.Print;  `\
`  ``<s>`{=html}`Method_Ref: `` `` := Print'``;``</s>`{=html}`  `\
`  `\
`  Some_Package.Print (Message);  `\
`  Message.Print;                 `\
`  Print;                         `\
`  ``<s>`{=html}`Method_Ref.``;``</s>`{=html}`                `\
`                                 `\
` Main;`

But note that `Message.Print'``;` is
illegal, you have to use a renaming declaration as above.

Since only mode conformance is required (and not full conformance as
between specification and body), parameter names and default values may
be changed with renamings:

`P (X: ``Integer :=  0);`\
`R (A: ``Integer := -1) ``P;`

## See also

### Wikibook

-   Ada Programming
-   Ada Programming/Operators

### Ada 95 Reference Manual

-
-
### Ada 2005 Reference Manual

-
-
### Ada Quality and Style Guide

-
Programming}}\|Subprograms

es:Programación en
Ada/Subprogramas


# Ada Programming/Packages

Ada encourages the division of code into separate modules called
*packages*. Each package can contain any combination of items.

Some of the benefits of using packages are:

-   package contents are placed in a separate namespace, preventing
    naming collisions,
-   implementation details of the package can be hidden from the
    programmer (information hiding),
-   object orientation requires defining a type and its primitive
    subprograms within a package, and
-   packages that are library units can be separately compiled.

Some of the more common package usages are:

-   a group of related subprograms along with their shared data, with
    the data not visible outside the package,
-   one or more data types along with subprograms for manipulating those
    data types, and
-   a generic package that can be instantiated under varying conditions.

The following is a quote from the current Ada Reference Manual

## Separate compilation

Note: The following chapters deal with packages on *library level*. This
is the most common use, since packages are the basic code structuring
means in Ada. However, Ada being a block oriented language, packages can
be declared at any level in any declarative region. In this case, the
normal visibility rules apply, also for the package body.

Package specifications and bodies on library level are compilation
units, so can be separately compiled. Ada has nothing to say about how
and where compilation units are stored. This is implementation
dependent. (Most implementations indeed store compilation units in files
of their own; name suffixes vary, GNAT uses `.ads` and `.adb`,
APEX `.1.ada` and
`.2.ada`.) The package body can itself be divided into multiple parts by
specifying that subprogram implementations or bodies of nested packages
are **separate**. These are then further compilation units.

One of the biggest advantages of Ada over most other programming
languages is its well-defined system of modularization and separate
compilation. Even though Ada allows separate compilation, it maintains
the strong type checking among the various compilations by enforcing
rules of compilation order and compatibility checking. Ada compilers
determine the compilation sequence; no make file is needed. Ada uses
separate compilation (like Modula-2,
Java and
C#), and not independent
compilation (as
C/C++ does),
in which the various parts are compiled with no knowledge of the other
compilation units with which they will be combined.

A note to C/C++ users: Yes, you can use the preprocessor to emulate
separate compilation --- but it is only an emulation and the smallest
mistake leads to very hard to find bugs. It is telling that all C/C++
successor languages including D
have turned away from the independent compilation and the use of the
preprocessor.

So it\'s good to know that Ada has had separate compilation ever since
Ada-83 and is probably the most sophisticated implementation around.

## Parts of a package

A package generally consists of two parts, the specification and the
body. A package specification can be further divided in two logical
parts, the visible part and the private part. Only the visible part of
the specification is mandatory. The private part of the specification is
optional, and a package specification might not have a package
body---the package body only exists to complete any *incomplete* items
in the specification. Subprogram declarations are the most common
*incomplete* items. There must not be a package body if there is no
incomplete declaration, and there has to be a package body if there is
some incomplete declaration in the specification.

To understand the value of the three-way division, consider the case of
a package that has already been released and is in use. A change to the
visible part of the specification will require that the programmers of
all using software verify that the change does not affect the using
code. A change to the private part of the declaration will require that
all using code be recompiled but no review is normally needed. Some
changes to the private part can change the meaning of the client code
however. An example is changing a private record type into a private
access type. This change can be done with changes in the private part,
but change the semantic meaning of assignment in the clients code. A
change to the package body will only require that the file containing
the package body be recompiled, because *nothing* outside of the package
body can ever access anything within the package body (beyond the
declarations in the specification part).

A common usage of the three parts is to declare the existence of a type
and some subprograms that operate on that type in the visible part,
define the actual structure of the type (e.g. as a record) in the
private part, and provide the code to implement the subprograms in the
package body.

### The package specification --- the visible part

The visible part of a package specification describes all the subprogram
specifications, variables, types, constants etc. that are visible to
anyone who wishes to use the package.

` Public_Only_Package `\
\
`  `` Range_10 `` `` 1 .. 10;`\
\
` Public_Only_Package;`

Since Range_10 is an integer type, there are a lot of operations
declared implicitly in this package.

### The private part

The private part of a package serves two purposes:

-   To complete the deferred definition of private types and constants.
-   To export entities only visible to the children of the package.

` Package_With_Private `\
`     `\
`   `` Private_Type `` ``;`\
\
\
\
`   `` Private_Type `` `` (1 .. 10) `` Integer;`\
\
` Package_With_Private;`

Since the type is private, clients cannot make any use of it as long as
there are no operations defined in the visible part.

### The package body

The package body defines the implementation of the package. All the
subprograms defined in the specification have to be implemented in the
body. New subprograms, types and objects can be defined in the body that
are not visible to the users of the package.

` Package_With_Body `\
\
`   `` Basic_Record `` ``;`\
\
`   `` Set_A (This : `` `` Basic_Record;`\
`                    An_A : ``     Integer);`\
\
`   `` Get_A (This : Basic_Record) `` Integer;`\
\
\
\
`   `` Basic_Record `` `\
`      `` `\
`         A : Integer;`\
`      `` `` ;`\
\
`   ``  (Get_A);  -- not a standard Ada pragma`\
`   `` (Get_A);`\
`   `` (Set_A);`\
\
` Package_With_Body;`

` `` Package_With_Body `\
\
`   `` Set_A (This : `` `` Basic_Record;`\
`                    An_A : ``     Integer) `\
`   `\
`      This.A := An_A;`\
`   `` Set_A;`\
\
`   `` Get_A (This : Basic_Record) `` Integer `\
`   `\
`      `` This.A;`\
`   `` Get_A;`\
\
` Package_With_Body;`

: Only available when using GNAT.

### Two Flavors of Package

The packages above each define a type together with operations of the
type. When the type\'s composition is placed in the private part of a
package, the package then exports what is known to be an Abstract Data
Type or ADT for short. Objects of the
type are then constructed by calling one of the subprograms associated
with the respective type.

A different kind of package is the Abstract State Machine or ASM. A
package will be modeling a single item of the problem domain, such as
the motor of a car. If a program controls one car, there is typically
just one motor, or *the* motor. The public part of the package
specification only declares the operations of the module (of the motor,
say), but no type. All data of the module are hidden in the body of the
package where they act as state variables to be queried, or manipulated
by the subprograms of the package. The initialization part sets the
state variables to their initial values.

` Package_With_Body `\
\
`   `` Set_A ``An_A `` `` Integer`\
\
`   `` Get_A `` Integer`\
\
\
\
`   `` Pure_Function ``Get_A``—not a standard Ada pragma`\
\
` Package_With_Body`

` `` Package_With_Body `\
\
`   The_A`` Integer`\
\
`   `` Set_A ``An_A `` `` Integer`` `\
`   `\
`      The_A `` An_A`\
`   `` Set_A`\
\
`   `` Get_A `` Integer `\
`   `\
`      `` The_A`\
`   `` Get_A`\
\
\
\
\
`   The_A `` 0`\
\
` Package_With_Body`

(A note on construction: The package initialization part after
 corresponds to a construction subprogram
of an ADT package. However, as a state machine *is* an "object" already,
"construction" is happening during package initialization. (Here it sets
the state variable `The_A` to its initial value.) An ASM package can be
viewed as a singleton.)

## Using packages

To utilize a package it\'s needed to name it in a **with** clause,
whereas to have direct visibility of that package it\'s needed to name
it in a **use** clause.

For C++ programmers, Ada\'s **with** clause is analogous to the C++
preprocessor\'s **#include** and Ada\'s **use** is similar to the
**using namespace** statement in C++. In particular, **use** leads to
the same namespace pollution problems as **using namespace** and thus
should be used sparingly. Renaming can shorten long compound names to a
manageable length, while the **use type** clause makes a type\'s
operators visible. These features reduce the need for plain **use**.

### Standard with

The standard with clause provides visibility for the public part of a
unit to the following defined unit. The imported package can be used in
any part of the defined unit, including the body when the clause is used
in the specification.

### Private with

` `` Ada.Strings.Unbounded; `\
\
` Private_With `\
\
`   `\
\
`   `` Basic_Record `` ``;`\
\
`   `` Set_A (This : `` `` Basic_Record;`\
`                    An_A : ``     String);`\
\
`   `` Get_A (This : Basic_Record) `` String;`\
\
\
`   `\
\
`   `` Unbounded `` Ada.Strings.Unbounded;`\
\
`   `` Basic_Record `` `\
`      `` `\
`         A : Unbounded.Unbounded_String;`\
`      `` ``;`\
\
`   ``  (Get_A);`\
`   `` (Get_A);`\
`   `` (Set_A);`\
\
` Private_With;`

` `` Private_With `\
\
`   `\
\
`   `` Set_A (This : `` `` Basic_Record;`\
`                    An_A : ``     String)`\
`   `\
`   `\
`      This.A := Unbounded.To_Unbounded_String (An_A);`\
`   `` Set_A;`\
\
`   `` Get_A (This : Basic_Record) `` String `\
`   `\
`      `` Unbounded.To_String (This.A);`\
`   `` Get_A;`\
\
` Private_With;`

### Limited with

The limited with can be used to represent two mutually dependent type
(or more) located in separate packages.

` `` Departments;`\
\
` Employees `\
\
`   `` Employee `` `` ``;`\
\
`   `` Assign_Employee`\
`     (E : `` `` Employee;`\
`      D : `` Departments.Department'``);`\
\
`   `` Dept_Ptr `` `` `` Departments.Department'``;`\
\
`   `` Current_Department(E : `` Employee) `` Dept_Ptr;`\
`   ...`\
` Employees;`

` `` Employees;`\
\
` Departments `\
\
`   `` Department `` `` ``;`\
\
`   `` Choose_Manager`\
`     (Dept    : `` `` Department;`\
`      Manager : `` Employees.Employee'``);`\
`   ...`\
` Departments;`

### Making operators visible

Suppose you have a package Universe that defines some numeric type T.

` Universe`\
` P `\
`  V`` Universe``T `` 10``0`\
\
`  V `` V `` 42``0``  `\
` P`

This program fragment is illegal since the operators implicitly defined
in Universe are not directly visible.

You have four choices to make the program legal.

Use a use_package_clause. This makes **all declarations** in Universe
directly visible (provided they are not hidden because of other
homographs).

` Universe`\
`  Universe`\
` P `\
`  V`` Universe``T `` 10``0`\
\
`  V `` V `` 42``0`\
` P`

Use renaming. This is error prone since if you rename many operators,
cut and paste errors are probable.

` Universe`\
` P `\
`  `` "*" ``Left`` Right`` Universe``T`` `` Universe``T `` Universe``"*"`\
`  `` "/" ``Left`` Right`` Universe``T`` `` Universe``T `` Universe``"*"``  `\
`  V`` Universe``T `` 10``0`\
\
`  V `` V `` 42``0`\
` P`

Use qualification. This is extremely ugly and unreadable.

` Universe`\
` P `\
`  V`` Universe``T `` 10``0`\
\
`  V `` Universe``"*" ``V`` 42``0`\
` P`

Use the use_type_clause. This makes only the **operators** in Universe
directly visible.

` Universe`\
` P `\
`  V`` Universe``T `` 10``0`\
`  `` `` Universe``T`\
\
`  V `` V `` 42``0`\
` P`

There is a special beauty in the use_type_clause. Suppose you have a set
of packages like so:

` Universe`\
` Pack `\
`  `` T `` Universe``T`\
` Pack`

` Pack`\
` P `\
`  V`` Pack``T `` 10``0`\
\
`  V `` V `` 42``0``  `\
` P`

Now you\'ve got into trouble. Since Universe is not made visible, you
cannot use a use_package_clause for Universe to make the operator
directly visible, nor can you use qualification for the same reason.
Also a use_package_clause for Pack does not help, since the operator is
not defined in Pack. The effect of the above construct means that the
operator is not nameable, i.e. it cannot be renamed in a renaming
statement.

Of course you can add Universe to the context clause, but this may be
impossible due to some other reasons (e.g. coding standards); also
adding the operators to Pack may be forbidden or not feasible. So what
to do?

The solution is simple. Use the use_type_clause for Pack.T and all is
well!

` Pack`\
` P `\
`  V`` Pack``T `` 10``0`\
`  `` `` Pack``T`\
\
`  V `` V `` 42``0`\
` P`

## Package organisation

### Nested packages

A nested package is a package declared inside a package. Like a normal
package, it has a public part and a private part. From outside, items
declared in a nested package N will have visibility as usual; the
programmer may refer to these items using a full dotted name like
`P.N.X`. (But not `P.M.Y`.)

` P `\
`   D`` Integer`\
\
`   `\
`   `` N `\
`      X`` Integer`\
`   `\
`      Foo`` Integer`\
`   `` N`\
\
`   E`` Integer`\
\
`   `\
`   `` M `\
`      Y`` Integer`\
`   `\
`      Bar`` Integer`\
`   `` M`\
\
` P`

Inside a package, declarations become visible as they are introduced, in
textual order. That is, a nested package N that is declared *after* some
other declaration D can refer to this declaration D. A declaration E
following N can refer to items of N.[^1] But neither can "look ahead"
and refer to any declaration that goes after them. For example, spec `N`
above cannot refer to `M` in any way.

In the following example, a type is derived in both of the two nested
packages `Disks` and `Books`. Notice that the full declaration of parent
type `Item` appears before the two nested packages.

` `` `` `\
\
` Shelf `\
\
`   `` Elaborate_Body`\
\
`   `\
\
`   `` ID `` `` 1_000 `` 9_999`\
`   `` Item ``Identifier `` ID`` `` `` `` `` `` `\
`   `` Item_Ref `` `` `` Item`\
\
`   `` Next_ID `` ID`\
`   `\
\
\
`   `` Disks `\
\
`      `` Music `` `\
`         Jazz`\
`         Rock`\
`         Raga`\
`         Classic`\
`         Pop`\
`         Soul`\
\
`      `` Disk ``Style `` Music`` Identifier `` ID`` `` `` Item ``Identifier`\
`         `` `\
`            Artist `` Unbounded_String`\
`            Title  `` Unbounded_String`\
`         `` `\
\
`   `` Disks`\
\
\
`   `` Books `\
\
`      `` Literature `` `\
`         Play`\
`         Novel`\
`         Poem`\
`         Story`\
`         Text`\
`         Art`\
\
`      `` Book ``Kind `` Literature`` Identifier `` ID`` `` `` Item ``Identifier`\
`         `` `\
`            Authors `` Unbounded_String`\
`            Title   `` Unbounded_String`\
`            Year    `` Integer`\
`         `` `\
\
`   `` Books`\
\
`   `\
\
`   `` Put ``it`` Item_Ref`\
`   `` Get ``identifier `` ID`` `` Item_Ref`\
`   `` Search ``title `` String`` `` ID`\
\
\
\
`   `\
\
`   `` Boxes `\
`      `` Treasure``Identifier`` ID`` `` `` `\
`   `\
`      `` Treasure``Identifier`` ID`` `` `` Item``Identifier`` `` `` `\
`   `` Boxes`\
\
` Shelf`

A package may also be nested inside a subprogram. In fact, packages can
be declared in any declarative part, including those of a block.

### Child packages

Ada allows one to extend the functionality of a unit (package) with
so-called children (child packages). With certain exceptions, all the
functionality of the parent is available to a child. This means that all
public and private declarations of the parent package are visible to all
child packages.

The above example, reworked as a hierarchy of packages, looks like this.
Notice that the package
 is not needed by the
top level package `Shelf`, hence its with clause doesn\'t appear here.
(We have added a match function for searching a shelf, though):

` Shelf `\
\
`   `` Elaborate_Body`\
\
`   `` ID `` `` 1_000 `` 9_999`\
`   `` Item ``Identifier `` ID`` `` `` `` `` `` `\
`   `` Item_Ref `` `` `` Item`\
\
`   `` Next_ID `` ID`\
`   `\
\
`   `` match ``it `` Item`` Text `` String`` `` Boolean `` `\
`   `\
\
\
`   `\
\
`   `` Put ``it`` Item_Ref`\
`   `` Get ``identifier `` ID`` `` Item_Ref`\
`   `` Search ``title `` String`` `` ID`\
\
` Shelf`

The name of a child package consists of the parent unit\'s name followed
by the child package\'s identifier, separated by a period (dot)
\`\'.

` `` `` `\
\
` Shelf``Books `\
\
`   `` Literature `` `\
`      Play`\
`      Novel`\
`      Poem`\
`      Story`\
`      Text`\
`      Art`\
\
`   `` Book ``Kind `` Literature`` Identifier `` ID`` `` `` Item ``Identifier`\
`      `` `\
`         Authors `` Unbounded_String`\
`         Title   `` Unbounded_String`\
`         Year    `` Integer`\
`      `` `\
\
`   `` match``it`` Book`` text`` String`` `` Boolean`\
\
` Shelf``Books`

`Book` has two components of type `Unbounded_String`, so
 appears in a with
clause of the child package. This is unlike the nested packages case
which requires that all units needed by any one of the nested packages
be listed in the context clause of the enclosing package (see
).
Child packages thus give better control over package dependences. With
clauses are more local.

The new child package `Shelf.Disks` looks similar. The `Boxes` package
which was a nested package in the private part of the original `Shelf`
package is moved to a private child package:

` `` Shelf``Boxes `\
`    `` Treasure``Identifier`` ID`` `` `` `\
\
`    `` Treasure``Identifier`` ID`` `` `` Item``Identifier`` `` `` `\
`    `` match``it`` Treasure`` text`` String`` `` Boolean`\
` Shelf``Boxes`

The privacy of the package means that it can only be used by equally
private client units. These clients include private siblings and also
the bodies of siblings (as bodies are never public).

Child packages may be listed in context clauses just like normal
packages. A  of a child also \'withs\'
the parent.

### Subunits

A subunit is just a feature to move a body into a place of its own when
otherwise the enclosing body will become too large. It can also be used
for limiting the scope of context clauses.

The subunits allow to physically divide a package into different
compilation units without breaking the logical unity of the package.
Usually each separated subunit goes to a different file allowing
separate compilation of each subunit and independent version control
history for each one.

` `` `` Pack `\
`   `` Proc `` `\
` `` Pack`\
\
` `` Some_Unit`\
` `` ``Pack`\
` `` Proc `\
` `\
`   ...`\
` `` Proc`

## Notes

```{=html}
<references/>
```
## See also

### Wikibook

-   Ada Programming

### Wikipedia

-   Module "wikilink")

### Ada 95 Reference Manual

-
### Ada 2005 Reference Manual

-
Programming}}\|Packages Ada
Programming}}/Unfinished module\|Packages

es:Programación en
Ada/Paquetes

[^1]: For example, `E: Integer := D + N.X;`


# Ada Programming/Input Output

## Overview

The standard Ada libraries provide several Input/Output facilities, each
one adapted to specific needs. Namely, the language defines the
following dedicated packages:

-   Text_IO
-   Sequential_IO
-   Direct_IO
-   Stream_IO

The programmer must choose the adequate package depending on the
application needs. For example, the following properties of the data
handled by the application should be considered:

-   **Data contents**: plain text, or binary data?
-   **Accessing the data**: random access, or sequential access?
-   **Medium**: data file, console, network/data-bus?
-   **Data structure**: homogeneous file (sequence of the same data
    field), heterogeneous file (different data fields)?
-   **Data format**: adherence to an existing data format, or the
    application can freely choose a new one?

For example, Stream_IO is very powerful and can handle complex data
structures but can be heavier than other packages; Sequential_IO is lean
and easy to use but cannot be used by applications requiring random data
access; Text_IO can handle just textual data, but it is enough for
handling the command-line console.

The following table gives some advices for choosing the more adequate
one:

  Data access   Plain text      Binary data
  ------------- --------------- ---------------
  Homogeneous   Heterogeneous
  Sequential    Text_IO         Sequential_IO
  Random        Stream_IO       Direct_IO

  : **Simple heuristics for choosing an I/O package**

So the most important lesson to learn is choosing the right one. This
chapter will describe more in detail these standard packages, explaining
how to use them effectively. Besides these Ada-defined packages for
general I/O operations each Ada compiler usually has other
implementation-defined Input-Output facilities, and there are also other
external libraries for specialized I/O
needs like XML
processing or interfacing with databases.

## Text I/O

Text I/O is probably
the most used Input/Output package. All data inside the file are
represented by human readable text. Text I/O provides support for line
and page layout but the standard is free form text.

` `\
` `\
` Main `\
`  Str  `` String ``1 `` 80`\
`  Last `` Natural`\
\
`  Ada``Text_IO``Get_Line ``Str`` Last`\
`  Ada``Text_IO``Put_Line ``Str ``1 `` Last`\

This example copies text from standard input to standard output when all
lines are shorter than 80 characters, the string length. See package
Text I/O how to deal
with longer lines.

The package also contains several generic packages for converting
numeric and enumeration types to character strings; there are child
packages for handling Bounded and Unbounded strings, allowing the
programmer to read and write different data types in the same file
easily (there are ready-to-use instantiations of these generic packages
for the Integer, Float, and Complex types). Finally, the same family of
Ada.Text_IO packages (including the several children and instantiation
packages) for the type Wide_Character and Wide_Wide_Character.

It is worth noting that the family of Text_IO packages provide some
automatic text processing. For example, the Get procedures for numeric
and enumeration types ignore white space at the beginning of a line
(Get_Line for String does not present this behavior), or adding line and
page terminators when closing the file. This is thus adequate for
applications handling simple textual data, but users requiring direct
management of text (e.g. raw access to the character encoding) must
consider other packages like Sequential_IO.

## Direct I/O

Direct I/O is used for random access files which contain only elements
of one specific type. With Direct_IO you can position the file pointer
to any element of that type `<small>`{=html}(random
access)`</small>`{=html}, however you can\'t freely choose the element
type, the element type needs to be a definite
subtype.

## Sequential I/O

Direct I/O is used for random access files which contain only elements
of one specific type. With Sequential_IO it is the other way round: you
can choose between
definite and
indefinite
element types but you have to read and write the elements one after the
other.

## Stream I/O

Stream I/O is the most powerful input/output package which Ada provides.
Stream I/O allows you to mix objects from different element types in one
sequential file. In order to read/write from/to a stream each type
provides a \'Read and
\'Write attribute as
well as an \'Input and
\'Output attribute.
These attributes are automatically generated for each type you declare.

The \'Read and
\'Write attributes treat
the elements as raw data. They are suitable for low level input/output
as well as interfacing with other programming languages.

The \'Input and
\'Output attributes add
additional control information to the file, like for example the
\'First and
\'Last attributes for an
array.

In object orientated programming you can also use the
\'Class\'Input
and
\'Class\'Output
attributes - they will store and recover the actual object type as well.

Stream I/O is also the most flexible input/output package. All I/O
attributes can be replaced with user defined functions or procedures
using representation clauses and you can provide your own Stream I/O
types using flexible object oriented techniques.

## See also

### Wikibook

-   Ada Programming
-   Ada
    Programming/Libraries/Ada.Direct_IO
-   Ada
    Programming/Libraries/Ada.Sequential_IO
-   Ada
    Programming/Libraries/Ada.Streams
    -   Ada
        Programming/Libraries/Ada.Streams.Stream_IO
    -   Ada
        Programming/Libraries/Ada.Text_IO.Text_Streams
-   Ada
    Programming/Libraries/Ada.Text_IO
    -   Ada
        Programming/Libraries/Ada.Text_IO.Enumeration_IO
        (nested package)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Integer_IO
        (nested package)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Modular_IO
        (nested package)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Float_IO
        (nested package)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Fixed_IO
        (nested package)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Decimal_IO
        (nested package)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Bounded_IO
    -   Ada
        Programming/Libraries/Ada.Text_IO.Unbounded_IO
    -   Ada
        Programming/Libraries/Ada.Text_IO.Complex_IO
        (specialized needs annex)
    -   Ada
        Programming/Libraries/Ada.Text_IO.Editing
        (specialized needs annex)
-   Ada
    Programming/Libraries/Ada.Integer_Text_IO
-   Ada
    Programming/Libraries/Ada.Float_Text_IO
-   Ada
    Programming/Libraries/Ada.Complex_Text_IO
    (specialized needs annex)
-   Ada
    Programming/Libraries/Ada.Storage_IO
    (not a general-purpose I/O package)
-   Ada
    Programming/Libraries/Ada.IO_Exceptions
-   Ada
    Programming/Libraries/Ada.Command_Line
-   Ada
    Programming/Libraries/Ada.Directories
-   Ada
    Programming/Libraries/Ada.Environment_Variables
-   Ada
    Programming/Libraries/GNAT.IO
    (implementation defined)
-   Ada
    Programming/Libraries/GNAT.IO_Aux
    (implementation defined)
-   Ada
    Programming/Libraries/GNAT.Calendar.Time_IO
    (implementation defined)
-   Ada
    Programming/Libraries/System.IO
    (implementation defined)
-   Ada Programming/Libraries
    -   Ada
        Programming/Libraries/GUI
    -   Ada
        Programming/Libraries/Web
    -   Ada
        Programming/Libraries/Database
-   Ada Programming/Platform
-   Ada
    Programming/Platform/Linux
-   Ada
    Programming/Platform/Windows

### Ada Reference Manual

-
-
-
-
-
-
-
-
### Ada 95 Quality and Style Guide

-       -
    -
    -
    -
    -
Programming}}\|InputOutput es:Programación
en Ada/Entrada-salida