# 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

