Goal
Write a multi-statement function … end with locals and an if, understand
what it returns, and Read a .g file you wrote in your own editor - so you can
keep real work in scratch/ instead of retyping at the prompt.
Concept
The arrow x -> expr (Lesson 04) is syntactic sugar for a one-line function. For anything
with several statements, local variables, or a conditional you write the full
form:
f := function(args)
local v1, v2;
…statements…
return value;
end;
local declares names private to the function (forget it and GAP warns about
globals). A function returns value when it hits return; with no return it
returns nothing. Read("file.g") executes a file as if you'd typed it - the way
you'll load scratch/*.g. Our target is a small chk(name, got, want) verifier;
building it earns the whole language vocabulary at once.
Commands to try
double := function(x) return 2*x; end;
double(21);
Expect 42. The body is one return; end closes it (no od/fi here, just
end).
classify := function(n)
if n < 0 then
return "negative";
elif n = 0 then
return "zero";
else
return "positive";
fi;
end;
List([-2, 0, 5], classify);
Expect [ "negative", "zero", "positive" ]. Note elif/fi, and that a named
function composes with List exactly like an arrow does.
Locals and a real helper
sumsq := function(L)
local r, s;
r := 0;
for x in L do
r := r + s^2;
od;
return r;
end;
sumsq([1,2,3,4]);
Expect 30. r and s are local - they don't leak into your session. Drop
the local line and re-enter it: GAP prints a warning about r/s being made
global. That warning is worth provoking once, so you get familiar with it showing up.
The chk harness (a self-check verifier)
This is a common pattern for scripting checks. It prints OK/FAIL and records a failure flag.
ok := true;;
chk := function(name, got, want)
if got = want then
Print(" OK ", name, " = ", got, "\n");
else
Print(" FAIL ", name, " = ", got, " (expected ", want, ")\n");
ok := false;
fi;
end;;
chk("two plus two", 2+2, 4);
chk("a wrong one", 2+2, 5);
ok;
Predict ok before the last line: one check failed, so what is it? Notice chk
reads and writes the global ok: that's deliberate here (it's not in the
local list), a handy way to accumulate a pass/fail verdict across many checks.
Reading a file
In your editor, create scratch/warmup.g containing, say:
sq := function(x) return x^2; end;;
Print("warmup.g loaded; sq(9) = ", sq(9), "\n");
Then in GAP:
Read("scratch/warmup.g");
sq(9);
The file runs; sq is now defined in your session. This is how you'll load
larger scripts from here on - write in your editor, Read it in, test at the
prompt.
Predict-then-check
Before running, predict the return value and whether anything prints:
mystery := function(n) local i; for i in [1..n] do od; end;
mystery(3);
(Trick: the loop body is empty and there's no return. What does GAP show for
the value of mystery(3)?)
Exercise
- Write
isperfectsquare := function(n) … endreturningtrue/falseusingRootInt. Test it withFiltered([1..30], isperfectsquare). - Extend the
chkharness: add achkn(name, got, want)that on failure also prints the differencegot - want. Reuse the same globalok. - Put
isperfectsquareand onechk(...)call intoscratch/lesson06.g,Readit, and confirm both the function and the OK line appear. - Report what
mystery(3)evaluated to and why.
Pitfalls
function … end, notfunction … endfunction. Blocks inside still usefi/od; only the function itself closes withend.- Forgetting
localmakes loop/temp variables global and triggers a warning - and can clobber a session variable of the same name. Declare locals. - No
return(or a barereturn;) means the function returns nothing; calling it at the prompt prints nothing. That's a feature for side-effect functions likePrint-only helpers. Read("path")takes a string and runs relative to GAP's current directory (where you launched it). IfRead"does nothing," you're likely in the wrong directory - check withDirectoryCurrent()or launch GAP from the repo root.- A function closing over a global (like
chkoverok) is intentional here but is exactly the kind of shared state to keep deliberate, not accidental.