[Ada Information Clearinghouse]
Ada '83 Rationale, Sec 3.4: Names

"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 3: Classical Programming

3.4 Names

A single object declaration associates an identifier with a declared object. The identifier, like every lexical element, is only a sequence of characters. But by virtue of the declaration, it becomes possible to use the identifier to refer to the declared object. We say that the identifier is a name for the object: a name that denotes the object. As we shall see, there are several forms of name. The simplest form is just an identifier, which is therefore also called a simple name.

To illustrate other forms of name, consider the following declarations (given in skeletal, but hopefully self-explanatory form):

type PERSON(SEX : GENDER) is
  record
    BIRTH :  DATE;
    ...
    SPOUSE :   ...   ;
  end record;

subtype KING is  PERSON(SEX =>  M);

JOHN  :  KING;
LOUIS :  array (1 .. 18) of KING;

The above declarations have defined several simple names: for example JOHN is the simple name of an object of subtype KING, and LOUIS is the simple name of an array of kings. Now, starting with simple names, we can form more complex names: a selected component such as

    JOHN.SPOUSE

which denotes a component of the record object that is itself denoted by JOHN; and similarly an indexed component such as

    LOUIS (9)

which denotes a particular component of our array of kings. We can also combine selected components and indexed components to form yet more complex names such as

LOUIS(15).SPOUSE

but not as in PL/1

    LOUIS.SPOUSE(15)

Following Simula (and unlike Pascal), Ada allows function calls to be part of names. For example we can define a function HEIR as follows:

function HEIR(N : POSITIVE) return KING is
begin
  if N < 18 then
    return LOUIS(N + 1);
  else
    raise LINEAGE_ERROR;
  end if;
end;

Now we can form names such as

    HEIR(14).SPOUSE

which include function calls. Note that the function call HEIR(14) delivers a value (not a variable), so that the above name allows the SPOUSE component to be read, but not updated.

The ability to use function calls in names is especially useful when dealing with data structures constructed with access types. Thus an algorithm in a tree traversal may include names such as

    NEXT(N).PART

where NEXT(N) delivers an access value, and where PART is a component of the object designated by the access value. In this case, reading and updating of the component PART are both possible.

This ability goes some way toward the principle of uniform referents advocated by Ross and others [Ro 70, GM 75]. Following this principle, Ada uses round brackets rather than square brackets for denoting array components, thereby unifying the syntax of indexed components and function calls. In the same spirit, the syntax of selected components is used for component selection of records, whether the records are statically or dynamically allocated (see 6.3.4).


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