What will happen if we will declare
Random as an attribute? Let’s try!
First we will create new attribute
MyRandom for objects in the category
MyRandom := NewAttribute("MyRandom", IsCollection);
Now we install a generic method which just returns
InstallMethod( MyRandom, "for a collection", [IsCollection], coll -> Random(coll) );
So far so good: each call returns new value:
gap> x:=[1..100]; [ 1 .. 100 ] gap> MyRandom(x); 88 gap> MyRandom(x); 6 gap> MyRandom(x); 98
Next we install a specific method for a group:
InstallMethod( MyRandom, "for a group", [IsGroup], G -> Random(G) );
and it does not work any more:
gap> G:=SymmetricGroup(5); Sym( [ 1 .. 5 ] ) gap> MyRandom(G); (1,3,4,2) gap> MyRandom(G); (1,3,4,2) gap> MyRandom(G); (1,3,4,2)
The reason is that the object from the 1st example is not in an attribute-storing representation, so despite
MyRandom has been declared as an attribute, new calculation is performed each time it is being called. In the 2nd example, the group has an attribute-storing representation, and the value of the first call of
MyRandom is stored in it and is never recalculated again.
This is an equivalent of XKCD’s “Random Number” in GAP!