Record (computer science)
A record, in computer science, took physical form as a single punched card, one card equaling one entry in the 1890 United States census. That same idea still describes a record today: a fixed bundle of separate facts about one thing. Whatever we call it now, that bundle still sits near the center of almost every modern computer system. But how did a paper technology built for tabulating census counts become a basic building block of software? Which programming languages embraced it early, which resisted it, and why do some programmers now call it obsolete while others insist it is still essential?
A date can be stored as a record: a numeric year field, a month represented as a string, and a numeric day-of-month field. A circle record works the same way, holding a numeric radius alongside a center that is itself a point record with x and y coordinates.
Formally, a record, also called a structure, struct, or user-defined type, bundles fields whose number and order usually stay constant. Those fields can still differ from one another in type.
Two main applications stand out. One is the record type built into a programming language. The other is row-based storage, where data such as a database table, spreadsheet, or CSV file is organized as a sequence of records. In general, a record type value lives in memory, while row-based storage lives in mass storage.
A record type itself is simply the data type describing such values and variables, and most modern languages let programmers define new ones. Defining a new record type means specifying the data type of each field. It also means giving each field an identifier, a name or label, by which it can be accessed.
In type theory, product types, which drop field names entirely, are generally favored for their simplicity. Proper record types, though, are still studied in languages such as System F-sub. Because type-theoretical records can hold first-class function-typed fields alongside plain data, they end up expressing many features associated with object-oriented programming.
Inside a database or spreadsheet, the same structure gets renamed: a record becomes a row, and each field becomes a column. In object-oriented programming, an object is essentially a record that also carries state and method fields.
A record also resembles a mathematical tuple. Whether a tuple counts as a record, or a record as a tuple, depends on the conventions of the particular programming language. Viewed that way, a record type is the computer-language analog of the Cartesian product of two or more mathematical sets. It can also be seen as the implementation of an abstract product type in a specific language.
An array, by contrast, is a collection of elements that all share the same type. A record's fields, in comparison, are set by its definition and may be heterogeneous.
At a low level, every function call carries an activation record, or call frame. That structure holds the parameters plus other fields, such as local variables and the return address. Seen this way, a function's parameters work like fields in a record, and passing arguments is like assigning values into those fields.
That layered relationship, parameters folding into fields, fields folding into records, is one reason the concept eventually shaped how entire databases and object systems get built.
The idea of gathering separate facts into one bundled entry predates computers by centuries, appearing in accounting ledgers used since remote times. Babbage's Analytical Engine, a 19th century mechanical calculator, already implied the modern notion of records, complete with fields of well-defined type and size.
A journal entry from 1880 sits beside a punch card from 1895, marking the era's shift from paper ledgers to machine-readable cards. Records were well established by the first half of the 20th century, when most data processing ran on punched cards. Each record of a data file typically lived on one card, with specific columns assigned to specific fields.
A record was generally the smallest chunk of data that could be pulled from external storage, such as a card reader, tape, or disk. Punchcard-style contents were originally called unit records, since punchcards had to conform to pre-determined document lengths.
When storage systems advanced to hard drives and magnetic tape, variable-length records became the standard. In such a record, the size in bytes roughly matches the sum of its fields' sizes. That flexibility only became possible once machines no longer required every card to be physically fed in at a pre-determined length.
Most machine language implementations and early assembly languages lacked special syntax for records. Programmers built the concept anyway, using index registers, indirect addressing, and self-modifying code. Some early computers, such as the IBM 1620, had hardware support for delimiting records and fields, plus special instructions for copying them.
The concept of records and fields sat at the center of early file sorting and tabulating utilities, including IBM's Report Program Generator. That utility set the stage for how full programming languages would soon treat structured data.
By the time record types spread widely across programming languages, COBOL had already gotten there first, with unusually sophisticated record definitions for its era. Its definitions allowed nested records with alphanumeric, integer, and fractional fields of arbitrary size and precision. Some fields even auto-formatted values, inserting currency signs, decimal points, and digit group separators. Each COBOL file was tied to a record variable, the place where data got read in or written out. A MOVE CORRESPONDING statement let the language assign matching fields between two records by their names.
FORTRAN, up through FORTRAN IV, and ALGOL 60 skipped record types entirely, since both were built for numeric computing. Later versions, FORTRAN 77 and ALGOL 68, added them. The original Lisp lacked records too, apart from its built-in cons cell, though its S-expressions served as an adequate stand-in. Pascal became one of the first languages to fully fold record types into a single, logically consistent type system alongside its other basic types. PL/I offered COBOL-style records, while C provided the same idea through structs. Most languages designed after Pascal, including Ada, Modula, and Java, adopted records as well.
Java 17 introduced its own version of records, and C# added records under its own name too. Java's records were meant to simplify data aggregate classes with less boilerplate. Fields became final and private automatically, while the compiler generated an all-argument constructor, getters, and the equals, hashCode, and toString methods. Every Java record also implicitly extends java.lang.Record. It is the newest entry in a long line of language-specific choices about how to declare, name, and use these bundles of fields.
A record type can be declared, fixing the position, type, and name of each field. A record itself can then be declared as a variable of that type. From there, a program can construct a record value, possibly setting initial field values, and read or write individual fields. Two records can also be compared for equality, or reduced to a single hash value.
Some languages let a program enumerate the fields of a record, a facility needed for debugging, garbage collection, and serialization. That facility requires some degree of type polymorphism.
In languages that support record subtyping, a record with fields x, y, and z belongs to the type of records with fields x and y. The same record would also belong to a type with fields x, y, and r. The rationale is that a function expecting an (x,y) record should still accept an (x,y,z) record. It will find every field it actually needs inside that larger record. Subtyping like this trips up many practical implementations, even though it remains a central idea in more theoretical treatments of record types.
Most languages will only assign one record to another when both share exactly the same record type: same field types, same names, same order. Even two separately defined record types with identical fields may still count as distinct types, depending on the language.
The same rules that govern assignment also govern equality comparisons between two record values. Some languages allow order comparisons too, using '<' and '>' based on the lexicographic order of individual fields. PL/I allows both styles of assignment, and it also permits structure expressions such as a = a+1. There, a is a record, called a structure in PL/I's own terminology.
In Algol 68, if Pts is an array of records each holding integer fields X and Y, a programmer can write Y of Pts. That expression pulls out an array of integers, the Y field from every element of Pts. As a result, writing Y of Pts3 := 7 and (Y of Pts)3 := 7 produces exactly the same effect.
In Pascal, the command with R do S runs the statements in S directly. It behaves as though every field of record R had been declared as its own separate variable. Much like switching to a different namespace in an object-oriented language such as C#, it removes the need to prefix field access with its name. Instead of writing Pt.X := 5; Pt.Y := Pt.X + 3 in full each time, a programmer using with can drop the repeated prefix entirely.
Fields inside a record usually sit in consecutive memory locations, arranged in the same order the record type declares them. That layout sometimes packs two or more fields into the very same word of memory, a trick systems programmers use to reach specific bits directly. Most compilers add padding fields that stay invisible to the programmer, to satisfy alignment rules. A floating point field, for example, may need to occupy a single full word.
Some languages implement a record instead as an array of addresses, each pointing to a field and possibly to that field's name or type. Objects in object-oriented languages often get implemented in far more complicated ways, especially wherever a language allows multiple class inheritance.
A self-defining record carries its own map: information that identifies the record's type and locates the data inside it. It may store the offsets of each element, which then lets those elements sit in any order, or even be left out entirely. That stored information works like metadata, similar to the UNIX metadata attached to a file: a creation time, and the record's size in bytes. Alternatively, each element can simply follow the next in any order, so long as every element carries its own identifier.
That same idea of identifying elements by a carried label, rather than by fixed position, reappears in how records get indexed for fast lookup.
An employee file might contain an employee number, a name, a department, and a salary. The employee number stays unique across the whole organization, making it the primary key, since no duplicate of a primary key may exist. Depending on how the file is organized, that employee number might also be indexed, stored separately to make lookups faster. The department code, by contrast, is not necessarily unique, so it might be indexed too, this time as a secondary key or alternate key. Without that index, the entire employee file would need scanning just to list every employee in one department. Keys generally get chosen to minimize how often several different values might map to the same key. That rules out something like the salary field, since many employees are likely to earn the same amount.
Records are rarely used anymore purely to hold data on their own. Even so, they shaped the newer object-oriented languages and relational database systems that followed them. Because records added modularity to how data was stored and handled, they suited complex, real-world concepts better than a language's primitive data types ever could. That same modularity later shaped C++, Python, JavaScript, and Objective-C, languages built to meet the same needs. Objects in those languages are records with methods and inheritance layered on top, letting programmers control how data behaves, not just what it contains.
Some programmers now consider records obsolete, arguing that object-oriented languages offer far more than a bare record ever could. Others counter that a record's low overhead, and its usefulness in assembly language, keep it relevant for low-level programming. Most of today's most popular languages on the TIOBE index, a gauge of programming language popularity, have been shaped by records. That is largely because those languages are object-oriented. Query languages such as SQL and Object Query Language carry that same influence. They let programmers store sets of records inside tables and retrieve specific ones using a primary key.
Even the tables themselves count as records. Any one of them may carry a foreign key, a field that reaches into another table to reference its data.
Common questions
What is a record in computer science?
A record in computer science is a composite data structure made up of a collection of fields, which can differ in type but are typically fixed in number and sequence. It is also called a structure, struct, or user-defined type.
What is an example of a record in computer science?
A date can be stored as a record with a numeric year field, a month field represented as a string, and a numeric day-of-month field. A circle record can hold a numeric radius alongside a center point record with x and y coordinates.
How does a record differ from an array in computer science?
A record's fields are set by its definition and may be heterogeneous, holding different types, while an array is a collection of elements that all share the same type.
Which programming language was the first to widely support record types?
COBOL was the first widely used programming language to support record types, with sophisticated record definition facilities that included nested records and automatic field formatting.
When did Java and C# add record types to the language?
Java introduced records in Java 17, and C# introduced its own version of records as well, both aiming to simplify data aggregate classes with less boilerplate code.
What is the difference between a primary key and a secondary key in a computer science record?
A primary key is unique throughout all stored records, with no duplicates allowed, such as an employee number in an employee file. A secondary key, or alternate key, such as a department code, is not necessarily unique but can still be indexed to speed up lookups.
All sources
16 references cited across the entry
- 1BookHow To Design ProgramsMatthias Felleisen — MIT Press — 2001
- 3BookDatabase Management SystemsTibor Radványi — Eszterházy Károly College — 2014
- 4BookIntroduction to Database Management SystemsAtul Kahate — Pearson — 2006
- 5BookDatabase Solutions: A Step by Step Guide to Building DatabasesThomas Connolly — Pearson — 2004
- 6JournalRecord data structures in racket: usage analysis and optimizationTobias Pape et al. — 2017-01-13
- 7JournalCharles Babbage's Analytical Engine, 1838Allan Bromley — October 1998
- 9BookEncyclopedia of computer scienceWiley — 2003
- 10BookConcepts of Programming LanguagesRobert W. Sebesta — Addison-Wesley Publishing Company, Inc. — 1996
- 11BookProceedings of the European conference on object-oriented programming on Object-oriented programming systems, languages, and applications - OOPSLA/ECOOP '90Gary T. Leavens et al. — ACM Press — 1990
- 14EPICS Input / Output Controller (IOC) Application Developer's GuideMartin R. Kraimer