[Ada Information Clearinghouse]
Ada '83 Rationale, Sec 4.1: Introduction (to Ch 4: Types)

"Rationale for the Design of the
Ada® Programming Language"

[Ada '83 Rationale, HTML Version]

Copyright ©1986 owned by the United States Government. All rights reserved.
Direct inquiries to the Ada Information Clearinghouse at adainfo@sw-eng.falls-church.va.us.

CHAPTER 4: Types

4.1 Introduction

The notion of type has gradually emerged from the past twenty years of the history of programming languages as the way by which we impose structure on data. A now widely accepted view of types is that a type characterizes the set of values that objects of the type may assume, and the set of operations that may be performed on them. This common view is also taken in the Ada language.

There are several important reasons why it is found desirable to associate a type with constants and variables:

Factorization of Properties, Maintainability
Knowledge about common properties of objects should be described and collected in one place and a name should be associated with that description. A type declaration serves that purpose. Subsequently, the type name may be used to refer to the common properties in object declarations. This factorization improves program maintainability: if later a given property is to be changed, then the type declaration will be the only part of the program text to be affected by the change.

Objects with distinct properties should be clearly distinguished in a program, and the distinction should be enforced by the compiler. Requiring that all objects be typed thus contributes to program reliability. Experience has shown that a well-written program in Pascal can be recognized easily by the use made of the typing facility to increase the reliability, readability, and security of the program.

Abstraction, Hiding of Implementation Details
Abstract or external properties of objects and operations should be separated from underlying and internal implementation-dependent properties, such as the physical representation on a specific machine. The abstract properties of an object are the only ones that need to be known for its use. Implementation details should therefore be hidden from the user. The need for such a separation is particularly strong in the case of disjoint sections of a program text, produced and maintained by different programmers, and presumably separately compiled.
Several classical problems are associated with the formulation of a type facility in a programming language. Some are the subject of ongoing debate among language designers and users, in particular:
(a) Static versus Dynamic Properties
Should both the static properties - those which are determinable from an analysis of the program text at compilation time - and the dynamic properties - those which may depend on the dynamic execution of a program, such as reading from an input device - be covered by a single notion of type?

(b) Type Equivalence
Should the language provide some form of equivalence or compatibility among types with logically related properties?

(c) Parameterization
Should the language provide some form of parameterization for types and their associated properties? Should the evaluation of type parameters be performed at translation time or should it be deferred until execution time?
The Ada solutions to the above problems are now summarized. A detailed discussion of these design decisions is given in later sections of this chapter.
(a) Static versus Dynamic Properties

Two notions are distinguished: the notion of type and the notion of subtype. A type characterizes a distinct set of values and its static properties, such as the applicable operations.

Constraints may be imposed on named types: for example a range constraint for a scalar type, or an index constraint for an array type. In general, constraints define certain requirements whose satisfaction is to be checked dynamically. A subtype name serves as an abbreviation for a type name together with a constraint associated with the type. Several difficulties in the types of Pascal that have been noted by Habermann and others [Hab 73, WSH 77] are overcome in Ada by the notion of subtype.

(b) Type Equivalence

Each type declaration defines a distinct type. In consequence, each type name denotes a distinct type. Values of a given type can be assigned only to objects that have this type. Values of different types cannot be intermixed.

In contrast, objects that have different subtypes of the same type are compatible: the value of an object may be assigned to a variable that has the same type, whether or not the object and the variable have the same subtype. Constraints are normally checked at execution time, although in many cases these checks can be done at compilation time, in anticipation.

Certain explicit conversions are allowed between closely related types. Such explicit conversions are defined among numeric types, among sufficiently similar array types, and among derived types of the same family. Being explicit, these conversions are safe. On the other hand, no implicit conversion is possible among user-defined types.

(c) Parameterization

Parameterization at execution time is closely associated with the notion of constraint. In particular this applies to array and record types:

Parameterization at compilation time is achieved by the very powerful mechanism of generic units. Whereas parameterization at execution time by index bounds and discriminants is limited to scalar values, the parameters of generic units can even be subprograms and types. For example, we could model the length of a stack by a discriminant; but, to allow for different types of elements, we would need to define stacks within a generic package and have the element type be a generic parameter. We could then create several instances of the generic package, for example one for stacks of integers, one for stacks of characters, and so on.

These solutions are detailed in the following sections of this chapter (and, in the case of generic units, in a later chapter). We first introduce the concept of type by means of the simplest form - enumeration types - and further use these types for the discussion of type equivalence and the concepts of constraints and subtypes. We then proceed to a discussion of array types, record types, and discriminants; and the general problems of type composition.

Address any questions or comments to adainfo@sw-eng.falls-church.va.us.