Ada Programming/Types/limited

Limited Types
When a type is declared this means that objects of the type cannot be assigned values of the same type. An Object b of limited type LT cannot be copied into an object a of same type LT.

Additionally, there is no predefined equality operation for objects of a limited type.

The desired effects of declaring a type limited include prevention of shallow copying. Also, the (unique) identity of an object is retained: once declared, a name of a variable of type LT will continue to refer to the same object.

The following example will use a rather simplifying type Boat.

Boat Choose Load  Sailors_Units Speed Sailors_Units Boat Set_Sail The_Boat   Boat

When we declare a variable to be of type Boat, its name will denote one boat from then on. Boats will not be copied into one another.

The full view of a boat might be implemented as a record such as

Boat Max_Sail_Area Sailors_Units Max_Freight   Sailors_Units Sail_Area     Sailors_Units Freight       Sailors_Units

The Choose function returns a <tt>Boat</tt> object depending on the parameters <tt>Load</tt> and <tt>Speed</tt>. If we now declare a variable of type Boat we will be better off Choosing an initial Boat (or else we might be dropping into uninitialized waters!). But when we do so, the initialization looks suspiciously like assignment which is not available with limited types:

Travel People Positive Average_Speed  Sailors_Units Henrietta Boat Choose Load  People  Average_Weight  15 Speed Average_Speed  15 Set_Sail Henrietta Travel

Fortunately, current Ada distinguishes initialization from copying. Objects of a limited type may be initialized by an initialization expression on the right of the delimiter .

(Just to prevent confusion: The Ada Reference Manual discriminates between assignment and assignment statement, where assignment is part of the assignment statement. An initialisation is of course an assignment which, for limited types, is done in place. An assignment statement involves copying, which is forbidden for limited types.)

Related to this feature are aggregates of limited types and “constructor functions” for limited types. Internally, the implementation of the <tt>Choose</tt> function will return a limited record. However, since the return type <tt>Boat</tt> is limited, there must be no copying anywhere. Will this work? A first attempt might be to declare a <tt>result</tt> variable local to <tt>Choose</tt>, manipulate <tt>result</tt>, and return it. The <tt>result</tt> object needs to be “transported” into the calling environment. But <tt>result</tt> is a variable local to <tt>Choose</tt>. When <tt>Choose</tt> returns, <tt>result</tt> will no longer be in scope. Therefore it looks like <tt>result</tt> must be copied but this is not permitted for limited types. There are two solutions provided by the language: extended return statements (see ) and aggregates of limited types. The following body of <tt>Choose</tt> returns an aggregate of limited type <tt>Boat</tt>, after finding the initial values for its components.

Choose Load  Sailors_Units Speed Sailors_Units Boat Capacity  Sailors_Units  Capacity_Needed Load Boat Max_Freight   Capacity Max_Sail_Area Sail_Needed Capacity Freight       Load Sail_Area     00 Choose

The object that is returned is at the same time the object that is to have the returned value. The function therefore initializes <tt>Henrietta</tt> in place.

In parallel to the predefined type <tt>.Controlled</tt>, Ada provides the type <tt>Limited_Controlled</tt> in the same package. It is a limited version of the former.

Initialising Limited Types
A few methods to initialise such types are presented.

Limited_Private_Samples Uninitialised   ; Preinitialised  ; Dynamic_Initialisation  ; Constructor (X: Integer) Dynamic_Initialisation; Needs_Constructor (<>)  ; Constructor (X: Integer) Needs_Constructor; Uninitialised I: Integer; ;   Preinitialised I: Integer := 0; ;   Void   ; Constructor (Object: Dynamic_Initialisation)  Void; Dynamic_Initialisation Hook: Void := Constructor (Dynamic_Initialisation'); Bla : Integer; ;   Needs_Constructor I: Integer; ; Limited_Private_Samples;

Limited_Private_Samples Constructor (Object: Dynamic_Initialisation)  Void Object.Bla := 5; ;   Constructor; Constructor (X: Integer) Dynamic_Initialisation (Hook =>,            Bla  => 42); Constructor; Constructor (X: Integer) Needs_Constructor (I => 42); Constructor; Limited_Private_Samples;

Limited_Private_Samples Limited_Private_Samples Try U Uninitialised P Preinitialised D1 Dynamic_Initialisation D2 Dynamic_Initialisation Constructor 0 D3 Dynamic_Initialisation Constructor 0 N Needs_Constructor Constructor 0 Try Note that D3 is a constant, whereas all others are variables.

Also note that the initial value that is defined for the component of Preinitialised is evaluated at the time of object creation, i.e. if an expression is used instead of the literal, the value can be run-time dependent.

X, Y: Preinitialised;

In this declaration of two objects, the initial expression will be evaluated twice and can deliver different values, because it is equivalent to the sequence:

X: Preinitialised; Y: Preinitialised;

So X is initialised before Y.