Lesson 2

Lists & indexing

Goal

In this lesson you will build a list, read and change its entries by index, slice it, grow it, and understand why two variables can point at the same list so that changing one changes the other.

Concept

A GAP list is an ordered, 1-indexed, mutable sequence written with square brackets: [2, 3, 5, 7]. Mutable means GAP stores a list once and a variable holds a reference to it. Two names can refer to one list; Add-ing through one name is visible through the other. This is the single biggest day-two surprise, so we meet it head-on. Lists are the universal container in GAP: generators, orbits, divisors, subgroup collections all come back as lists.

Commands to try

primes := [2, 3, 5, 7, 11];

A list of five integers. Note assignment is := (Lesson 01).

primes[1];

Expect 2. GAP is 1-indexed: the first element is [1], not [0]. Asking for primes[0] is an error, and primes[6] (past the end) is too.

Length(primes);

Expect 5.

primes[3] := 555;
primes;

Assignment into a slot mutates the list in place: [ 2, 3, 555, 7, 11 ].

primes{[2,4]};

Curly braces select a sublist by a list of positions: expect [ 3, 7 ]. Square brackets [i] give one element; curly {[...]} give a list of elements.

Add(primes, 13);
primes;

Add appends one element, mutating in place. Now length 6.

Append(primes, [17, 19]);
primes;

Append tacks on a whole list. (Add is for one element, Append is for many.)

The mutability trap - on purpose

a := [1, 2, 3];
b := a;
Add(b, 99);
a;

Predict before you look. a is now [ 1, 2, 3, 99 ] - even though you added to b. b := a copied the reference, not the contents; both names point at one list. To get an independent copy:

c := ShallowCopy(a);
Add(c, 7);
a;

a is unchanged this time. ShallowCopy duplicates the top-level list.

Predict-then-check

You have a = [ 1, 2, 3, 99 ]. Predict the result of each, in order, before typing:

a{[1..2]};
Position(a, 99);
99 in a;

(One is a sublist, one is an index, one is a boolean. Commit to all three.)

Exercise

  1. Make a list L := [10, 20, 30, 40, 50].
  2. Using a slice, pull out [20, 40] in one expression.
  3. Append 60 and 70 to it with a single Append.
  4. Create M := ShallowCopy(L), change M[1], and confirm L[1] did not change. Then redo it with M := L and confirm it did.
  5. Report what L[0] does, and what Length([]) returns.

Pitfalls

  • 1-indexed. L[1] is the first element. L[0] is an error.
  • A list is a reference. b := a aliases; use ShallowCopy(a) for an independent list. (Deep structures need StructuralCopy - later.)
  • [i] = one element; {[...]} = a sublist. Different brackets, different return type.
  • Add takes one element; Append takes a list. Add(L, [1,2]) adds the list [1,2] as a single nested element, which is rarely what you want.
  • Indexing past the end errors; assigning past the end (L[100] := x) actually grows the list with holes - something you might fail to iterate through. Holes are real and will bite you later.
← Back to Learning GAP - Part 1: Foundations