Function-Operation-Attribute Triples

&GAP; is eager to maintain information that it has gathered about an object, possibly by lengthy calculations. The most important mechanism for information maintenance is the automatic storage and look-up that takes place for attributes; and this was already mentioned in section . In this chapter we will describe further mechanisms that allow storage of results that are not values of attributes.

FOA triples
The idea which is common to all sections is that certain operations, which are not themselves attributes, have an attribute associated with them. To automatically delegate tasks to the attribute, &GAP; knows, in addition to the operation and the attributes also a function, which is wrapped around the other two. This wrapper function is called by the user and decides whether to call the operation or the attribute or possibly both. The whole function-operation-attribute triple (or FOA triple) is set up by a single &GAP; command which writes the wrapper function and already installs some methods, e.g., for the attribute to fall back on the operation. The idea is then that subsequent methods, which perform the actual computation, are installed only for the operation, whereas the wrapper function remains unaltered, and in general no additional methods for the attribute are required either.

Key Dependent Operations
<#Include Label="KeyDependentOperation">

In Parent Attributes
<#Include Label="InParentFOA">

Operation Functions
ExternalSet
G
-sets
Orbits
Chapter and, in particular, the Section explain that certain operations such as ), besides their usual usage with arguments G, D, and opr, can also be applied to an external set (G-set), in which case they can be interpreted as attributes. Moreover, they can also be interpreted as attributes for permutation groups, meaning the natural action on the set of its moved points.

The definition of says that a method should be a function with arguments G, D, gens, oprs, and opr, as in the case of the operation when specified via gens and oprs (see ). All other syntax variants allowed for (e.g., leaving out gens and oprs) are handled by default methods.

The default methods for support the following behaviour. If the only argument is an external set xset and the attribute tester HasOrbits( xset ) returns true, the stored value of that attribute is returned. If the only argument is an external set xset and the attribute value is not known, the default arguments are obtained from the data of xset. If gens and oprs are not specified, gens is set to Pcgs( G ) if CanEasilyComputePcgs( G ) is true, and to GeneratorsOfGroup( G ) otherwise; oprs is set to gens. The default value of opr is . In the case of an operation of a permutation group G on MovedPoints( G ) via , if the attribute tester HasOrbits( G ) returns true, the stored attribute value is returned. The operation is called as result:= Orbits( G, D, gens, oprs, opr ). In the case of an external set xset or a permutation group G in its natural action, the attribute setter is called to store result. result is returned.

The declaration of operations that match the above pattern is done as follows.

<#Include Label="OrbitsishOperation"> <#Include Label="OrbitishFO">

Example: Orbit and OrbitOp

For example, to setup the function and its operation OrbitOp, the declaration file lib/oprt.gd contains the following line of code: OrbitishFO( "Orbit", OrbitishReq, IsCollsElms, false, false ); The variable OrbitishReq contains the standard requirements OrbitishReq := [ IsGroup, IsList, IsObject, IsList, IsList, IsFunction ]; which are usually entered in calls to .

The relation test via famrel is used to provide a uniform construction of the wrapper functions created by , in spite of the different syntax of the specific functions. For example, admits the calls Orbit( G, D, pnt, opr ) and Orbit( G, pnt, opr ), i.e., the second argument D may be omitted; admits the calls Blocks( G, D, seed, opr ) and Blocks( G, D, opr ), i.e., the third argument may be omitted. The translation to the appropriate call of OrbitOp or BlocksOp, for either operation with five or six arguments, is handled via famrel.

As a consequence, there must not only be methods for OrbitOp with the six arguments corresponding to OrbitishReq, but also methods for only five arguments (i.e., without D). Plenty of examples are contained in the implementation file lib/oprt.gi.

In order to handle a few special cases (currently and ), also the following form of is supported.

OrbitishFO( name, reqs, famrel, attr )

The functions in question depend upon an argument seed, so they cannot be regarded as attributes. However, they are most often called without giving seed, meaning choose any minimal resp. maximal block system. In this case, the result can be stored as the value of the attribute attr that was entered as fourth argument of . This attribute is considered by a call Blocks( G, D, opr ) (i.e., without seed) in the same way as considers OrbitsAttr.

To set this up, the declaration file lib/oprt.gd contains the following lines: DeclareAttribute( "BlocksAttr", IsExternalSet ); OrbitishFO( "Blocks", [ IsGroup, IsList, IsList, IsList, IsList, IsFunction ], IsIdenticalObj, BlocksAttr, true ); And this extraordinary FOA triple works as follows: gap> s4 := Group((1,2,3,4),(1,2));; gap> Blocks( s4, MovedPoints(s4), [1,2] ); [ [ 1, 2, 3, 4 ] ] gap> Tester( BlocksAttr )( s4 ); false gap> Blocks( s4, MovedPoints(s4) ); [ [ 1, 2, 3, 4 ] ] gap> Tester( BlocksAttr )( s4 ); BlocksAttr( s4 ); true [ [ 1, 2, 3, 4 ] ]