Key Takeaways — Chapter 11: Records and Variant Records
Core Concepts
-
Records group related data of different types into a single unit. A
TStudentrecord bundles a name (string), ID (integer), GPA (real), and enrollment status (boolean) — something no array can do. -
Records eliminate parallel arrays. Instead of maintaining fragile, synchronized arrays (
Names[i],IDs[i],GPAs[i]), use a single array of records (Students[i].Name,.ID,.GPA). Data stays together during sorting, passing, and modification. -
Dot notation accesses fields:
RecordVariable.FieldName. For nested records, chain the dots:Employee.HomeAddress.City. For arrays of records:Roster[3].Name. -
Whole-record assignment copies all fields (
B := A), but whole-record comparison is not supported — compare individual fields instead. -
The WITH statement is a shortcut, not a best practice. It saves typing but introduces scope ambiguity. Use it only in short, clear blocks. When in doubt, use explicit dot notation.
-
Arrays of records are the standard way to represent tabular data in Pascal. They combine the collection power of arrays with the structuring power of records.
-
Variant records (tagged unions) enable polymorphic data. A single
TItemtype can represent weapons, potions, keys, and treasures — each with its own specific fields — using acasetag field. -
Always set the tag field before setting variant fields. Always check the tag field before reading variant fields. Variant fields share memory — accessing the wrong variant produces garbage.
-
Use
constfor record parameters that are read-only. This is more efficient than pass-by-value (avoids copying) and safer than pass-by-reference (prevents modification). -
Good record design mirrors the problem domain. One record type per concept, clear field names, appropriate field types (enums over strings for fixed categories), and count fields for partially-filled arrays.
Quick Reference
| Operation | Syntax |
|---|---|
| Define a record type | type TStudent = record ... end; |
| Declare a record variable | var S: TStudent; |
| Access a field | S.Name |
| Whole-record assignment | S2 := S1; |
| WITH shortcut | with S do begin Name := 'X'; end; |
| Array of records | var Roster: array[1..30] of TStudent; |
| Nested field access | Emp.Address.City |
| Variant record | case Kind: TKind of ... inside a record |
| Typed constant | const Default: TStudent = (Name: ''; ID: 0; ...); |
| Const parameter | procedure Show(const S: TStudent); |
Common Mistakes to Avoid
- Comparing records with
=— This does not compile. Compare fields individually. - Using
WITHin long blocks — Leads to ambiguity about whether names refer to fields or local variables. - Accessing the wrong variant — Setting
Kind := skCirclethen readingWidthyields garbage. - Forgetting the count field — Arrays inside records need a companion field tracking how many elements are in use.
- Defining types in the wrong order — If
TStudentusesTGradeArray, defineTGradeArrayfirst.
Connection to What Comes Next
- Chapter 12 combines records with file I/O — you will learn to save and load records to disk, making PennyWise's data persistent.
- Later chapters combine records with pointers to build linked lists, trees, and other dynamic data structures where records form the nodes.
- Variant records foreshadow object-oriented programming — they are Pascal's procedural approach to the same polymorphism problem that classes and inheritance solve.