Key Takeaways — Chapter 11: Records and Variant Records

Core Concepts

  1. Records group related data of different types into a single unit. A TStudent record bundles a name (string), ID (integer), GPA (real), and enrollment status (boolean) — something no array can do.

  2. 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.

  3. Dot notation accesses fields: RecordVariable.FieldName. For nested records, chain the dots: Employee.HomeAddress.City. For arrays of records: Roster[3].Name.

  4. Whole-record assignment copies all fields (B := A), but whole-record comparison is not supported — compare individual fields instead.

  5. 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.

  6. 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.

  7. Variant records (tagged unions) enable polymorphic data. A single TItem type can represent weapons, potions, keys, and treasures — each with its own specific fields — using a case tag field.

  8. 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.

  9. Use const for record parameters that are read-only. This is more efficient than pass-by-value (avoids copying) and safer than pass-by-reference (prevents modification).

  10. 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 WITH in long blocks — Leads to ambiguity about whether names refer to fields or local variables.
  • Accessing the wrong variant — Setting Kind := skCircle then reading Width yields 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 TStudent uses TGradeArray, define TGradeArray first.

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.