Lesson 5

Records

Goal

Use a record to bundle named fields, read and set them with ., and check which fields exist - the right container when position-in-a-list would be fragile.

Concept

A record is GAP's key→value structure, written rec( a := 1, b := "x" ). You reach a field by name with .: r.a. Where a list says "the third thing," a record says "the thing called top." Many GAP objects are records under the hood, and library data (structural info, options to functions) is passed as records. Records are mutable, like lists.

Commands to try

r := rec( name := "S4", order := 24, perfect := false );

A record with three fields. Inside rec( … ) the field assignments use :=.

r.order;

Expect 24. Dot-access by field name.

r.order := 240;
r;

Fields are mutable: reassigning r.order changes the record in place. (We lie to it here just to see mutation; reset with r.order := 24;.)

RecNames(r);

Expect a list of the field names as strings, e.g. [ "name", "order", "perfect" ]. Order of names is not guaranteed. Records are keyed by name, not position. This is the point of a record vs. a list: you never rely on "field number 2."

IsBound(r.order);
IsBound(r.degree);

Expect true then false. IsBound tests whether a field exists before you touch it. Trying to read an unbound field is an error, which you can guard with IsBound.

r.degree := 2;
RecNames(r);

You can add fields after creation just by assigning them. Now degree exists.

Unbind(r.degree);
IsBound(r.degree);

Unbind removes a field; now false again. (Unbind also works on list slots.)

Predict-then-check

Predict each, then check:

g := rec( gens := [ (1,2,3), (1,2) ], deg := 3 );
Length(g.gens);
IsBound(g.size);
RecNames(g);

(Note the parentheses: the values given in gens are permutations, which we'll cover in Lesson 07. Here just treat them as opaque list entries.)

Exercise

  1. Build a record describing a group: rec( name := "A5", aka := "Alt5", order := 60, perfect := true ).
  2. Add a field simple := true after creation.
  3. Write a ForAll over RecNames of your record that checks every field name has length ≥ 2. (Length of a string is its character count.)
  4. Use IsBound to safely return r.degree if present and 0 if not, in a single expression (hint: GAP has no ternary; an if … then … else … fi inside a function comes in Lesson 06 - for now just show the two IsBound results).

Pitfalls

  • Reading an unbound field errors. Guard with IsBound when you're not sure the field is there (common when library functions return optional fields).
  • Field names are bare identifiers after . and := inside rec(…), but RecNames returns them as strings. Don't mix r.name (field) with "name" (string) : RecNames gives the latter.
  • Records have no inherent field order; never depend on the order RecNames returns.
  • rec( a := 1 ) uses := for fields; a record is not a list and has no [i] indexing.
  • Like lists, records are references - s := r; s.order := 9; mutates r too. Use StructuralCopy for an independent record.
← Back to Learning GAP - Part 1: Foundations