Goal
Replace hand-written loops with List, Filtered, ForAll, ForAny,
Number, Set, and Sum : the idioms that make GAP scripts short and that
you'll reach for constantly.
Concept
GAP is heavily functional: instead of looping to build or test, you pass a
function to a combinator. The function is usually an arrow expression
x -> expr (anonymous, one argument, returns expr). List maps, Filtered
selects, ForAll/ForAny test, Number counts, Set dedupes-and-sorts. Lines
like Set(List(gens, Order)) and ForAny(divs, d -> d = 60) are exactly this
pattern.
Commands to try
List([1..5], x -> x^2);
Expect [ 1, 4, 9, 16, 25 ]. List(domain, f) applies f to each element -
this is "map". The x -> x^2 is a one-argument function written inline.
Filtered([1..20], n -> n mod 3 = 0);
Expect [ 3, 6, 9, 12, 15, 18 ]. Filtered(domain, test) keeps the elements
where test returns true. (mod is the remainder operator; = tests
equality.)
Number([1..20], n -> IsPrimeInt(n));
Expect 8 (the primes ≤ 20). Number counts how many satisfy the predicate
like Length(Filtered(...)) but direct.
ForAll([2,4,6,8], n -> n mod 2 = 0);
ForAny([1,3,5,6], n -> n mod 2 = 0);
Expect true then true. ForAll is ∀, ForAny is ∃. They short-circuit.
Set([3,1,2,3,1]);
Expect [ 1, 2, 3 ]. Set returns a strictly sorted, duplicate-free list:
a "set" in GAP is just a sorted list with no repeats. Set(List(...)) is the
standard way to get the distinct results of a map (e.g. the distinct element
orders in a group).
Sum(List([1..10], x -> x^2));
Expect 385. Combinators compose: map then sum.
Predict-then-check
Recreate the idiom on a toy. Predict each before evaluating:
divs := DivisorsInt(12);
Number(divs, d -> d > 3);
Set(List(divs, d -> d mod 3));
ForAll(divs, d -> 12 mod d = 0);
(DivisorsInt(12) is [1,2,3,4,6,12]. The last one asks: does every divisor
divide 12? - a tautology, so predict its truth value confidently.)
Exercise
- In one expression, get the list of squares of
1..10that are even. (ComposeFilteredandList, or filter on the square directly.) - Count how many integers in
1..100are divisible by both 2 and 5. - Using
SetandList, get the distinct last digits of the cubes1³…20³. - Write a
ForAllcheck that every element of[4,9,16,25]is a perfect square. (Hint:RootInt(n)^2 = n.) - Re-do Exercise 2 from Lesson 03 (the cubes list) as a single
Listcall.
Pitfalls
x -> exprtakes exactly one argument and returns the expression. For more arguments or multiple statements you need fullfunction … end(Lesson 06) - an arrow can't hold a;-separated body.Filtered/ForAll/Numberwant a predicate returningtrue/false;Listwants a function returning a value. Swapping them gives type-confusing results, not always an error.Set(L)returns a new sorted list; it does not sortLin place (that'sSort(L), which mutates and returns nothing).=is equality even inside these functions; never reach for:=in a predicate.- These read the whole domain. Over a giant group
List(G, …)will try to enumerate every element. That's fine forA5, fatal for a group with billions of elements.