06 Record Types
06 Record Types
hashed access to elements. An array can have elements that are created with
simple numeric indices and elements that are created with string hash keys.
In Lua, the table type is the only data structure. A Lua table is an associa-
tive array in which both the keys and the values can be any type. A table can be
used as a traditional array, an associative array, or a record (struct). When used
as a traditional array or an associative array, brackets are used around the keys.
When used as a record, the keys are the field names and references to fields can
use dot notation (record_name.field_name).
The use of Lua’s associative arrays as records is discussed in Section 6.7.
C# and F# support associative arrays through a .NET class.
An associative array is much better than an array if searches of the elements
are required, because the implicit hashing operation used to access elements
is very efficient. Furthermore, associative arrays are ideal when the data to be
stored is paired, as with employee names and their salaries. On the other hand,
if every element of a list must be processed, it is more efficient to use an array.
objects that reside in scattered locations, often on the heap. The elements of a
record are of potentially different sizes and reside in adjacent memory locations.
Records have been part of all of the most popular programming languages,
except pre-90 versions of Fortran, since the early 1960s, when they were intro-
duced by COBOL. In some languages that support object-oriented program-
ming, data classes serve as records.
In C, C++, and C#, records are supported with the struct data type. In
C++, structures are a minor variation on classes. In C#, structs are also related
to classes, but are also quite different. C# structs are stack-allocated value types,
as opposed to class objects, which are heap-allocated reference types. Structs
in C++ and C# are normally used as encapsulation structures, rather than data
structures. They are further discussed in this capacity in Chapter 11.Structs are
also included in ML and F#.
In Python and Ruby, records can be implemented as hashes, which them-
selves can be elements of arrays.
The following sections describe how records are declared or defined,
how references to fields within records are made, and the common record
operations.
The following design issues are specific to records:
• What is the syntactic form of references to fields?
• Are elliptical references allowed?
01 EMPLOYEE-RECORD.
02 EMPLOYEE-NAME.
05 FIRST PICTURE IS X(20).
05 MIDDLE PICTURE IS X(10).
05 LAST PICTURE IS X(20).
02 HOURLY-RATE PICTURE IS 99V99.
Ada uses a different syntax for records; rather than using the level numbers
of COBOL, record structures are indicated in an orthogonal way by simply
nesting record declarations inside record declarations. In Ada, records cannot be
anonymous—they must be named types. Consider the following Ada declaration:
In Java and C#, records can be defined as data classes, with nested records
defined as nested classes. Data members of such classes serve as the record fields.
As stated previously, Lua’s associative arrays can be conveniently used as
records. For example, consider the following declaration:
employee.name = "Freddie"
employee.hourlyRate = 13.20
Most of the other languages use dot notation for field references, where
the components of the reference are connected with periods. Names in dot
notation have the opposite order of COBOL references: They use the name
of the largest enclosing record first and the field name last. For example, the
following is a reference to the field Middle in the earlier Ada record example:
Employee_Record.Employee_Name.Middle
6.7 Record Types 279
C and C++ use this same syntax for referencing the members of their
structures.
References to elements in a Lua table can appear in the syntax of record
field references, as seen in the assignment statements in Section 6.7.1. Such
references could also have the form of normal table elements—for example,
employee["name"].
A fully qualified reference to a record field is one in which all intermedi-
ate record names, from the largest enclosing record to the specific field, are
named in the reference. Both the COBOL and the Ada example field refer-
ences above are fully qualified. As an alternative to fully qualified references,
COBOL allows elliptical references to record fields. In an elliptical reference,
the field is named, but any or all of the enclosing record names can be omitted,
as long as the resulting reference is unambiguous in the referencing environ-
ment. For example, FIRST, FIRST OF EMPLOYEE-NAME, and FIRST OF
EMPLOYEE-RECORD are elliptical references to the employee’s first name in the
COBOL record declared above. Although elliptical references are a program-
mer convenience, they require a compiler to have elaborate data structures and
procedures in order to correctly identify the referenced field. They are also
somewhat detrimental to readability.
6.7.3 Evaluation
Records are frequently valuable data types in programming languages. The
design of record types is straightforward, and their use is safe.
Records and arrays are closely related structural forms, and it is therefore
interesting to compare them. Arrays are used when all the data values have the
same type and/or are processed in the same way. This processing is easily done
when there is a systematic way of sequencing through the structure. Such process-
ing is well supported by using dynamic subscripting as the addressing method.
Records are used when the collection of data values is heterogeneous and
the different fields are not processed in the same way. Also, the fields of a record
often need not be processed in a particular order. Field names are like literal, or
constant, subscripts. Because they are static, they provide very efficient access
to the fields. Dynamic subscripts could be used to access record fields, but it
would disallow type checking and would also be slower.
Records and arrays represent thoughtful and efficient methods of fulfilling
two separate but related applications of data structures.
Figure 6.7
Record
A compile-time
Name
descriptor for a record
Field 1 Type
Offset
Name
Field n Type
Offset
Address
Notice that the elements of a tuple need not be of the same type.
The elements of a tuple can be referenced with indexing in brackets, as in
the following:
myTuple[1]
This references the first element of the tuple, because tuple indexing begins at 1.
Tuples can be catenated with the plus (+) operator. They can be deleted
with the del statement. There are also other operators and functions that
operate on tuples.
ML includes a tuple data type. An ML tuple must have at least two ele-
ments, whereas Python’s tuples can be empty or contain one element. As in