Sophie

Sophie

distrib > Mandriva > 2010.0 > i586 > media > contrib-release > by-pkgid > 5e1854624d3bc613bdd0dd13d1ef9ac7 > files > 258

gap-system-4.4.12-5mdv2010.0.i586.rpm

<html><head><title>[tut] 9 Migrating to GAP 4</title></head>
<body text="#000000" bgcolor="#ffffff">
[<a href="../index.htm">Top</a>] [<a href = "chapters.htm">Up</a>] [<a href ="CHAP008.htm">Previous</a>] [<a href ="CHAP010.htm">Next</a>] [<a href = "theindex.htm">Index</a>]
<h1>9 Migrating to GAP 4</h1><p>
<P>
<H3>Sections</H3>
<oL>
<li> <A HREF="CHAP009.htm#SECT001">Changed Command Line Options</a>
<li> <A HREF="CHAP009.htm#SECT002">Fail</a>
<li> <A HREF="CHAP009.htm#SECT003">Changed Functionality</a>
<li> <A HREF="CHAP009.htm#SECT004">Changed Variable Names</a>
<li> <A HREF="CHAP009.htm#SECT005">Naming Conventions</a>
<li> <A HREF="CHAP009.htm#SECT006">Immutable Objects</a>
<li> <A HREF="CHAP009.htm#SECT007">Copy</a>
<li> <A HREF="CHAP009.htm#SECT008">Attributes vs. Record Components</a>
<li> <A HREF="CHAP009.htm#SECT009">Different Notions of Generation</a>
<li> <A HREF="CHAP009.htm#SECT010">Operations Records</a>
<li> <A HREF="CHAP009.htm#SECT011">Operations vs. Dispatcher Functions</a>
<li> <A HREF="CHAP009.htm#SECT012">Parents and Subgroups</a>
<li> <A HREF="CHAP009.htm#SECT013">Homomorphisms vs. General Mappings</a>
<li> <A HREF="CHAP009.htm#SECT014">Homomorphisms vs. Factor Structures</a>
<li> <A HREF="CHAP009.htm#SECT015">Isomorphisms vs. Isomorphic Structures</a>
<li> <A HREF="CHAP009.htm#SECT016">Elements of Finitely Presented Groups</a>
<li> <A HREF="CHAP009.htm#SECT017">Polynomials</a>
<li> <A HREF="CHAP009.htm#SECT018">The Info Mechanism</a>
<li> <A HREF="CHAP009.htm#SECT019">Debugging</a>
<li> <A HREF="CHAP009.htm#SECT020">Compatibility Mode</a>
</ol><p>
<p>
This chapter is intended to give users who have experience with <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3
some information about what has changed in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
<p>
In particular, it informs about changed command line options
(see&nbsp;<a href="CHAP009.htm#SECT001">Changed Command Line Options</a>),
the new global variable <code>fail</code> (see&nbsp;<a href="CHAP009.htm#SECT002">Fail</a>),
some functions that have changed their behaviour
(see&nbsp;<a href="CHAP009.htm#SECT003">Changed Functionality</a>) or their names
(see&nbsp;<a href="CHAP009.htm#SECT004">Changed Variable Names</a>),
and some conventions used for variable names (see&nbsp;<a href="CHAP009.htm#SECT005">Naming Conventions</a>).
<p>
Then the new concepts of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 are sketched,
first that of mutability or immutability (see&nbsp;<a href="CHAP003.htm#SECT003">Immutability</a>),
with the explanation of related changes in functions that copy objects
(see&nbsp;<a href="CHAP009.htm#SECT007">Copy</a>),
then the concepts of operations and method selection, which are compared
with the use of operations records in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3
(see&nbsp;<a href="CHAP009.htm#SECT008">Attributes vs. Record Components</a>, <a href="CHAP009.htm#SECT010">Operations Records</a>,
and&nbsp;<a href="CHAP009.htm#SECT011">Operations vs. Dispatcher Functions</a>).
<p>
More local changes affect the concepts of notions of generation
(see&nbsp;<a href="CHAP009.htm#SECT009">Different Notions of Generation</a>),
of parents (see&nbsp;<a href="CHAP009.htm#SECT012">Parents and Subgroups</a>),
of homomorphisms (see&nbsp;<a href="CHAP009.htm#SECT013">Homomorphisms vs. General Mappings</a>,
<a href="CHAP009.htm#SECT014">Homomorphisms vs. Factor Structures</a>,
and&nbsp;<a href="CHAP009.htm#SECT015">Isomorphisms vs. Isomorphic Structures</a>),
how elements in finitely presented groups are treated
(see&nbsp;<a href="CHAP009.htm#SECT016">Elements of Finitely Presented Groups</a>),
how information about progress of computations can be obtained
(see&nbsp;<a href="CHAP009.htm#SECT018">The Info Mechanism</a>),
and how one gets information in a <code>break</code> loop
(see&nbsp;<a href="CHAP009.htm#SECT019">Debugging</a>).
<p>
While a ``<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 compatibility mode'' is provided
(see <a href="CHAP009.htm#SECT020">Compatibility Mode</a>),
its use will disable some of the new features of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
Also it certainly can only try to provide partial compatibility.
<p>
For a detailed explanation of the new features and concepts of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4,
see the manual ``Programming in GAP''.
<p>
<p>
<h2><a name="SECT001">9.1 Changed Command Line Options</a></h2>
<p><p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, the <code>-l</code> option is used to specify the <strong>root directory</strong>
(see&nbsp;<a href="../ref/CHAP009.htm#SECT002">GAP Root Directory</a> in the Reference Manual)
of the <font face="Gill Sans,Helvetica,Arial">GAP</font> distribution,
which is the directory containing the <code>lib</code> and <code>doc</code> subdirectories.
Note that in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 this option was used to specify the path to the
<code>lib</code> directory.
<p>
The <code>-h</code> option of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 has been removed,
the path(s) for the documentation are deduced automatically in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
<p>
The option <code>-g</code> is now used to print information only about full garbage
collections.
The new option <code>-g -g</code> generates  information about partial
garbage collections too.
<p>
<p>
<h2><a name="SECT002">9.2 Fail</a></h2>
<p><p>
There is a new global variable
<p>
<a name = "SSEC002.1"></a>
<li><code>fail</code>
<p>
in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
It is intended as a return value of a function for the case that it
could not perform its task.
For example, <code>Inverse</code> returns <code>fail</code> if it is called with a singular
matrix, and <code>Position</code> returns <code>fail</code> if the second argument is not
contained in the list given as first argument.
<p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 handled such situations by either signalling an error,
for example if it was asked for the inverse of a singular matrix,
or by (mis)using <code>false</code> as return value, as in the example <code>Position</code>.
Note that in the first example, in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 it was necessary to check
the invertibility of a matrix before one could safely ask for its
inverse, which meant that roughly the same work was done twice.
<p>
<p>
<h2><a name="SECT003">9.3 Changed Functionality</a></h2>
<p><p>
Some functions that were already available in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3  behave
differently in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.  This section lists them.
<p>
<a name = "SSEC003.1"></a>
<li><code>Orbit( </code><var>G</var><code>,</code><var>pnt</var><code>)</code>
<p>
The <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 manual promised that <var>pnt</var> would be the first entry of the
resulting orbit. This was wrong already there in a few cases, therefore
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 does not promise anything about the ordering of points in an orbit.
<p>
<a name = "SSEC003.2"></a>
<li><code>Order( </code><var>g</var><code> )</code>
<p>
only takes the element <var>g</var> and computes its multiplicative order.
Calling <code>Order</code> with two arguments is permitted only in the
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 compatibility mode, see&nbsp;<a href="CHAP009.htm#SECT020">Compatibility Mode</a>.
(Note that it does not make sense anymore to specify a group as
first argument w.r.t. which the order of the second argument shall
be computed, see&nbsp;<a href="CHAP009.htm#SECT016">Elements of Finitely Presented Groups</a>.)
<p>
<a name = "SSEC003.3"></a>
<li><code>Position( </code><var>list</var><code>, </code><var>obj</var><code> )</code>
<p>
If <var>obj</var> is not contained in the list <var>list</var> then <code>fail</code> is returned
in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 (see&nbsp;<a href="CHAP009.htm#SECT002">Fail</a>), whereas <code>false</code> was returned in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3.
<p>
<a name = "SSEC003.4"></a>
<li><code>PermGroupOps.ElementProperty( </code><var>G</var><code>, </code><var>prop</var><code>[, </code><var>K</var><code>] )</code>
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, this function took either two or three arguments,
the optional argument <var>K</var> being a subgroup of <var>G</var> that stabilizes <var>prop</var>
in the sense that for any element <var>g</var> in <var>G</var>,
either all elements or no element in the coset <code></code><var>g</var><code> * </code><var>K</var><code></code> have the
property <var>prop</var>.
<p>
The <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 function <code>ElementProperty</code>, however,
takes between two and four arguments,
and the subgroup <var>K</var> known from <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 has to be entered as the <strong>fourth</strong>
argument <strong>not</strong> the third.
(The third argument in the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 function denotes a subgroup <var>U</var>
stabilizing <var>prop</var> in the sense that either all elements or no element
in right cosets <code></code><var>U</var><code> * </code><var>g</var><code></code> have the property <var>prop</var>.)
<p>
(This discrepancy was discovered only in March&nbsp;2002,
short before the release of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.3.)
<p>
<a name = "SSEC003.5"></a>
<li><code>Print( </code><var>obj</var><code>, ... )</code>
<p>
Objects may appear on the screen in a different way,
depending on whether they are printed by the read eval print loop
or by an explicit call of <code>Print</code>.
The reason is that the read eval print loop calls the operation <code>ViewObj</code>
and not <code>PrintObj</code>, whereas <code>Print</code> calls <code>PrintObj</code> for each of its
arguments.
This permits the installation of methods for printing objects in a short form
in the read eval print loop while retaining <code>Print</code> to display
the object completely.
See also Section&nbsp;<a href="../ref/CHAP006.htm#SECT003">View and Print</a> in the Reference Manual.
<p>
(<code>PrintObj</code> is installed as standard method <code>ViewObj</code>, so it is
not really necessary to have a <code>ViewObj</code> method for an object.)
<p>
<a name = "SSEC003.6"></a>
<li><code>PrintTo( </code><var>filename</var><code>, </code><var>obj</var><code>, ... )</code>
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, <code>PrintTo</code> could be (mis)used to ``redirect'' the text
<strong>printed</strong> by a function (that is, <strong>not</strong> only the output of a function)
to a file by entering the function call as second argument.
This was used mainly in order to avoid many calls of <code>AppendTo</code>.
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, this feature has disappeared.
One can use streams (see Chapter&nbsp;<a href="../ref/CHAP010.htm">Streams</a> in the Reference Manual)
instead in order to write files efficiently.
<p>
<p>
<h2><a name="SECT004">9.4 Changed Variable Names</a></h2>
<p><p>
<a name = "I0"></a>

<a name = "I1"></a>

<a name = "I2"></a>

<a name = "I3"></a>

<a name = "I4"></a>

<a name = "I5"></a>

<a name = "I6"></a>

<a name = "I7"></a>

<a name = "I8"></a>

<a name = "I9"></a>

<a name = "I10"></a>

<a name = "I11"></a>

<a name = "I12"></a>

<a name = "I13"></a>

<a name = "I14"></a>

<a name = "I15"></a>

<a name = "I16"></a>

<a name = "I17"></a>

Some functions have changed their name without changing the
functionality.
A -- probably incomplete -- list follows
<pre>
    GAP 3                   GAP 4

    AgGroup                 PcGroup            # (also composita)
    ApplyFunc               CallFuncList
    Backtrace               Where
    CharTable               CharacterTable     # (also composita)
    Denominator             DenominatorRat
    DepthVector             PositionNot
    Elements                AsSSortedList
    IsBijection             IsBijective
    IsFunc                  IsFunction
    IsMat                   IsMatrix
    IsRec                   IsRecord
    IsSet                   IsSSortedList
    LengthWord              Length
    NOfCyc                  Conductor
    Numerator               NumeratorRat
    NormedVector            NormedRowVector
    Operation               Action            # (also composita)
    Order(G,g)              Order(g)
    OrderMat                Order
    OrderPerm               Order
    RandomInvertableMat     RandomInvertibleMat
    RecFields               RecNames
    X                       Indeterminate
</pre>
<p>
See Section&nbsp;<a href="CHAP009.htm#SECT020">Compatibility Mode</a> for a way to make the old names
available again.
<p>
<p>
<h2><a name="SECT005">9.5 Naming Conventions</a></h2>
<p><p>
The way functions are named has been unified in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
This might help to memorize or even guess names of library functions.
<p>
If a variable name consists of several words then the first
letter of each word is capitalized.
<p>
If the first part of the name of a function is a verb then the function
may modify its argument(s) but does not return anything,
for example <code>Append</code> appends the list given as second argument to the
list given as first argument.
Otherwise the function returns an object without changing the arguments,
for example <code>Concatenation</code> returns the concatenation of the lists
given as arguments.
<p>
If the name of a function contains the word <code>By</code> then the return value is
thought of as built in a certain way from the parts given as arguments.
For example, <code>GroupByGenerators</code> returns a group built from its group
generators, and creating a group as a factor group of a given group
by a normal subgroup can be done by taking the image of
<code>NaturalHomomorphismByNormalSubgroup</code>
(see also&nbsp;<a href="CHAP009.htm#SECT014">Homomorphisms vs. Factor Structures</a>).
Other examples of ``<code>By</code>'' functions are <code>GroupHomomorphismByImages</code> and
<code>UnivariateLaurentPolynomialByCoefficients</code>.
<p>
If the name of a function contains the word <code>Of</code> then the return value is
thought of as information deduced from the arguments.
Usually such functions are attributes
(see&nbsp;<a href="../tut/CHAP008.htm#SECT001">Attributes</a> in this Tutorial and&nbsp;<a href="../ref/CHAP013.htm#SECT005">Attributes</a>
in the Reference Manual).
Examples are <code>GeneratorsOfGroup</code>, which returns a list of generators for
the group entered as argument, or <code>DiagonalOfMat</code>.
<p>
For the setter and tester functions of an attribute <var>attr</var>
(see&nbsp;<a href="CHAP009.htm#SECT008">Attributes vs. Record Components</a> in this Tutorial
and&nbsp;<a href="../ref/CHAP013.htm#SECT005">Attributes</a> in the Reference Manual)
the names <code>Set</code><var>attr</var><code></code> resp.&nbsp;<code>Has</code><var>attr</var><code></code> are available.
<p>
If the name of a function <var>fun1</var> ends with <code>NC</code> then there is another
function <var>fun2</var> with the same name except that the <code>NC</code> is missing.
<code>NC</code> stands for ``no check''.
When <var>fun2</var> is called then it checks whether its arguments are valid,
and if so then it calls <var>fun1</var>.
The functions <code>SubgroupNC</code> and <code>Subgroup</code> are a typical example.
<p>
The idea is that the possibly time consuming check of the arguments
can be omitted if one is sure that they are unnecessary.
For example, if an algorithm produces generators of the derived subgroup
of a group then it is guaranteed that they lie in the original group;
<code>Subgroup</code> would check this, and <code>SubgroupNC</code> omits the check.
<p>
Needless to say, all these rules are not followed slavishly,
for example there is one operation <code>Zero</code> instead of two operations
<code>ZeroOfElement</code> and <code>ZeroOfAdditiveGroup</code>.
<p>
<p>
<h2><a name="SECT006">9.6 Immutable Objects</a></h2>
<p><p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 supports ``immutable'' objects.  Such objects cannot be
changed, attempting to do so issues an error.  Typically attribute
values are immutable, and also the results of those binary arithmetic
operations where both arguments are immutable, see Section&nbsp;<a href="CHAP003.htm#SECT008">Vectors and Matrices</a>.  For example, <code>[ 1 .. 100 ] + [ 1 .. 100 ]</code> is a
mutable list and <code>2 * Immutable( [ 1 .. 100 ] )</code> is an immutable
list, both are equal to the (mutable) list <code>[ 2, 4 .. 200 ]</code>.
<p>
There is no way to <strong>make</strong> an immutable object mutable, one can only
get a mutable copy by <code>ShallowCopy</code>.  The other way round,
<code>MakeImmutable</code> makes a (mutable or immutable) object and all its
subobjects immutable; one must be very careful to use <code>MakeImmutable</code>
only for those objects that are really newly created, for such objects
the advantage over <code>Immutable</code> is that no copy is made.
<p>
More about immutability can be found in Sections&nbsp;<a href="../tut/CHAP003.htm#SECT003">Immutability</a> in
this tutorial and&nbsp;<a href="../ref/CHAP012.htm#SECT006">Mutability and Copyability</a> in the Reference
Manual.
<p>
<p>
<h2><a name="SECT007">9.7 Copy</a></h2>
<p><p>
<a name = "I18"></a>

<a name = "I19"></a>

The function <code>Copy</code> of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 is not supported in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.  This
function was used to create a copy <var>cop</var> of its argument <var>obj</var> with
the properties that <var>cop</var> and <var>obj</var> had no subobjects in common and
that if two subobjects of <var>obj</var> were identical then also the
corresponding subobjects of <var>cop</var> were identical.
<p>
The possibility of having immutable objects (see&nbsp;<a href="CHAP003.htm#SECT003">Immutability</a>) can and
should be used to avoid unnecessary copying.
Namely, given an immutable object one needs to copy it only if one wants
to get a modified object, and in such a situation usually it is
sufficient to use <code>ShallowCopy</code>, or at least one knows how deep one must
copy in order to do the changes one has in mind.
<p>
For example, suppose you have a matrix group, and you want to
construct a list of matrices by modifying the group generators.  This
list of generators is immutable, so you call <code>ShallowCopy</code> to get a
mutable list that contains the same matrices.  If you only want to
exchange some of them, or to append some other matrices, this shallow
copy is already what you need.  So suppose that you are interested in
a list of matrices where some rows are also changed.  For that, you
call <code>ShallowCopy</code> for the matrices in question, and you get matrices
whose rows can be changed.  If you want to change single entries in
some rows, <code>ShallowCopy</code> must be called to get mutable copies of these
rows.  Note that in all these situations there is no danger to change,
i.e., to destroy the original generators of the matrix group.
<p>
If one needs the facility of the <code>Copy</code> function of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 to get a
copy with the same structure then one can use the new <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4
function <code>StructuralCopy</code>.  It returns a structural copy that has no
<strong>mutable</strong> subobject in common with its argument.  So if
<code>StructuralCopy</code> is called with an immutable object then this object
itself is returned, and if <code>StructuralCopy</code> is called with a mutable
list of immutable objects then a shallow copy of this list is
returned.
<p>
Note that <code>ShallowCopy</code> now is an operation.  So if you create your
own type of (copyable) objects then you must define what a shallow
copy of these objects is, and install an appropriate method.
<p>
<p>
<h2><a name="SECT008">9.8 Attributes vs. Record Components</a></h2>
<p><p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, many complex objects were represented via records, for
example all domains.  Information about these objects was stored in
components of these records.  For the user, this was usually not
relevant, since there were functions for computing information about
the objects in question.  For example, if one was interested in the
size of a group then one could call <code>Size</code>.
<p>
But since it was guaranteed that the size of a domain <var>D</var> was stored
as value of the component <code>size</code>, it was allowed to access <code></code><var>D</var><code>.size</code>
if this component was bound, and a check for this was possible via
<code>IsBound( </code><var>D</var><code>.size )</code>.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, only the access via functions is admissible.  One reason
is the following basic rule.
<p>
<strong>From the information that a given <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 object is for example a
domain, one cannot conclude that this object has a certain
representation.</strong>
<p>
For attributes like <code>Size</code>, <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 provides two related functions,
the <strong>setter</strong> and the <strong>tester</strong> of the attribute, which can be used to
set an attribute value and to check whether the value of an attribute
is already stored for an object (see also&nbsp;<a href="../ref/CHAP013.htm#SECT005">Attributes</a> in the
Reference Manual).  For example, if <var>D</var> is a domain in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 then
<code>HasSize( </code><var>D</var><code> )</code> is <code>true</code> if the size of <var>D</var> is already stored, and
<code>false</code> otherwise.  In the latter case, if you know that the size of
<var>D</var> is <var>size</var> then you may store it by <code>SetSize( </code><var>D</var><code>, </code><var>size</var><code> )</code>.
<p>
Besides the flexibility in the internal representation of objects,
storing information only via function calls has also the advantage
that <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 is able to draw conclusions automatically.  For example,
as soon as it is stored that a group is nilpotent, it is also stored
that it is solvable, see Chapters&nbsp;<a href="../ref/CHAP013.htm">Types of Objects</a> in the
Reference Manual and&nbsp;<a href="../prg/CHAP002.htm">Method Selection</a> in ``Programming in GAP''
for the details.
<p>
As a consequence, you cannot put your favourite information into a
domain <var>D</var> by assigning it to a new component like
<code></code><var>D</var><code>.myPrivateInfo</code>.  Instead you can introduce a new attribute and
then use its setter, see&nbsp;<a href="../ref/CHAP013.htm#SECT005">Attributes</a> in the Reference Manual.
<p>
<p>
<h2><a name="SECT009">9.9 Different Notions of Generation</a></h2>
<p><p>
As in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, a <strong>domain</strong> in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 is a structured set.
<p>
The same set can have different structures, for example a field can be
regarded as a ring or as an algebra or vector space over a subfield.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, however, an object representing a ring did not represent
a field, and an object representing a field did not represent a ring.
One reason for this was that the record component <code>generators</code> was
used to denote the appropriate generators of the domain.  For a ring
<var>R</var>, the component <code></code><var>R</var><code>.generators</code> was a list of ring generators, and
for a field <var>F</var>, <code></code><var>F</var><code>.generators</code> was a list of field generators.
<p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 cleans this up, see&nbsp;<a href="CHAP007.htm#SECT003">Notions of Generation</a>.  It supports
many different notions of generation, for example one can ask for
magma generators of a group or for generators of a field as an additive
group.  A subtle but important distinction is that between generators
of an algebra and of an algebra-with-one.
<p>
So the attributes <code>GeneratorsOfGroup</code>, <code>GeneratorsOfMagma</code>,
<code>GeneratorsOfRing</code>, <code>GeneratorsOfField</code>, <code>GeneratorsOfVectorSpace</code>,
and so on, replace the access to the <code>generators</code> component.
<p>
<p>
<h2><a name="SECT010">9.10 Operations Records</a></h2>
<p><p>
Already in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 there were several functions that were applicable
to many different kinds of objects, for example <code>Size</code> could be
applied to any domain, and the binary infix multiplication <code>*</code> could
be used to multiply two matrices, an integer with a row vector, or a
permutation with a permutation group.  This was implemented as
follows.  Functions like <code>Size</code> and <code>*</code> tried to find out what
situation was described by its arguments, and then it called a more
specific function to compute the desired information.  These more
specific functions, let us call them <strong>methods</strong> as they are also called
in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, were stored in so-called <strong>operations records</strong> of the
arguments.
<p>
For example, every domain in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 was represented as a record, and
the operations record was stored in the record component <code>operations</code>.
If <code>Size</code> was called for the domain then the method to compute the
size of the domain was found as value of the <code>Size</code> component of the
operations record.
<p>
This was fine for functions taking only one argument, and in principle
it is possible that for those functions an object stored an optimal
method in its operations record.  But in the case of more arguments
this is not possible.  In a multiplication of two objects in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3,
one had to choose between the methods stored in the operations records
of the arguments, and if for example the method stored for the left
operand was called, this method had to handle all possible right
operands.
<p>
So operations records turned out to be not flexible enough.  In
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, operations records are not supported (see&nbsp;<a href="CHAP009.htm#SECT020">Compatibility Mode</a> for a possibility to use your <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 code that utilizes
operations records, at least to some extent).  A detailed description
of the new mechanism to select methods can be found in
Chapter&nbsp;<a href="../prg/CHAP002.htm">Method Selection</a> in ``Programming in GAP''.
<p>
An important point is that the new mechanism allows <font face="Gill Sans,Helvetica,Arial">GAP</font> to take the
relation between arguments into account.  So it is possible (and
recommended) to install different methods for different relations
between the arguments.  Note that such methods need not do the
extensive argument checking that was necessary in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, because
most of the checks are done already by the method selection mechanism.
<p>
<p>
<h2><a name="SECT011">9.11 Operations vs. Dispatcher Functions</a></h2>
<p><p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 functions like <code>Size</code>, <code>CommutatorSubgroup</code>, or
<code>SylowSubgroup</code> did mainly call an appropriate method (see&nbsp;<a href="CHAP009.htm#SECT010">Operations Records</a>) after they had checked their arguments.  Such functions were
called <strong>dispatchers</strong> in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3.  In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, many dispatchers have
been replaced by <strong>operations</strong>, due to the fact that methods are no
longer stored in operations records (see&nbsp;<a href="../prg/CHAP002.htm">Method Selection</a> in
``Programming in GAP'' for the details).
<p>
Most dispatchers taking only one argument were treated in a special
way in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, they had the additional task of storing computed
values and using these values in subsequent calls.  For example, the
dispatcher <code>Size</code> first checked whether the size of the argument was
already stored, and if so then this value was returned; otherwise a
method was called, the value returned by this method was stored in the
argument, and then returned by <code>Size</code>.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, computed values of operations that take one argument
(these operations are called <strong>attributes</strong>) are also stored, only the
mechanism to achieve this has changed, see&nbsp;<a href="../ref/CHAP013.htm#SECT005">Attributes</a>
and&nbsp;<a href="../ref/CHAP013.htm#SECT007">Properties</a> in the Reference Manual.
<p>
So the behaviour of <code>Size</code> is the same in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 and <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.  But
note that in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, it is not possible to access <code></code><var>D</var><code>.size</code>,
see&nbsp;<a href="CHAP009.htm#SECT008">Attributes vs. Record Components</a>.  As described in&nbsp;<a href="CHAP009.htm#SECT010">Operations Records</a>, <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 does not admit ``bypassing the dispatcher'' by
calling for example <code></code><var>D</var><code>.operations.Size</code>.  This was done in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3
often for efficiency reasons, but the method selection mechanism of
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 is fast enough to make this unnecessary.
<p>
If you had written your own dispatchers and put your own methods into
existing operations records then this code will not work in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
See&nbsp;<a href="../prg/CHAP003.htm">Creating New Objects</a> and&nbsp;<a href="../prg/CHAP002.htm">Method Selection</a> in
``Programming in GAP'' for a description of how to define operations
and to install methods.
<p>
Finally, some functions in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 were hidden in
operations records, e.g., <code>PermGroupOps.MovedPoints</code>.
These functions became proper operations in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
<p>
<p>
<h2><a name="SECT012">9.12 Parents and Subgroups</a></h2>
<p><p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 there was a strict distinction between parent groups and
subgroups.
The use of the name ``parent'' (instead of ``supergroup'')
was chosen to indicate that the parent of an object was more than just
useful information.
In fact the main reason for the introduction of parents was to provide
a common roof for example for all groups of polycyclic words that
belonged to the same PC-presentation, or for all subgroups of a finitely
presented group (see&nbsp;<a href="CHAP009.htm#SECT016">Elements of Finitely Presented Groups</a>).
A subgroup was never a parent group, and it was possible to create
subgroups only of parent groups.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 this common roof is provided already by the concept of
<strong>families</strong>, see&nbsp;<a href="../ref/CHAP013.htm#SECT001">Families</a> in the Reference Manual.
Thus it is no longer compulsory to use parent groups at all.
On the other hand, parents <strong>may</strong> be used in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 to provide
information about an object, for example the normalizer of a group in its
parent group may be stored as an attribute value.
Note that there is no restriction on the supergroup that is set to be
the parent,
it is possible to create a subgroup of
any group, this group then being the parent of the new subgroup.
This permits for example chains of subgroups with respective parents,
of arbitrary length.
<p>
As a consequence, the <code>Parent</code> command cannot be used in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 to
test whether the two arguments of <code>CommutatorSubgroup</code> fit together,
this is now a question that concerns the relation between the families
of the groups.  So the 2-argument version of <code>Parent</code> and the now
meaningless function <code>IsParent</code> have been abolished.
<p>
<p>
<h2><a name="SECT013">9.13 Homomorphisms vs. General Mappings</a></h2>
<p><p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 there had been a confusion between group homomorphisms and
general mappings, as <code>GroupHomomorphismByImages</code> created only a
general mapping that did <strong>not</strong> store whether it was a mapping.  This
caused expensive, unwanted, and unnecessary tests whether the mapping
was in fact a group homomorphism.  Moreover, the ``official''
workaround to set some components of the mapping record was quite
unwieldy.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, <code>GroupHomomorphismByImages</code> checks whether the desired
mapping is indeed a group homomorphism; if so then this property is
stored in the returned mapping, otherwise <code>fail</code> is returned.  If you
want to avoid the checks then you can use
<code>GroupHomomorphismByImagesNC</code>.  If you want to check whether a general
mapping that respects the group operations is really a group
homomorphism, you can construct it via <code>GroupGeneralMappingByImages</code>
and then call <code>IsGroupHomomorphism</code> for it.  (Note that
<code>IsGroupHomomorphism</code> returns <code>true</code> if and only if both
<code>IsGroupGeneralMapping</code> and <code>IsMapping</code> do, so one does in fact check
<code>IsMapping</code> in this case.)
<p>
There is <strong>no</strong> function <code>IsHomomorphism</code> in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4,
since there are several different operations with respect to which a
mapping can be a homomorphism.
<p>
<p>
<h2><a name="SECT014">9.14 Homomorphisms vs. Factor Structures</a></h2>
<p><p>
If <i>F</i> is a factor structure of <i>G</i>, with kernel <i>N</i>, complete
information about the connection between <i>F</i> and <i>G</i> is provided by
the <strong>natural homomorphism</strong>.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, the ``official way'' to construct this natural homomorphism
was to create first the factor structure <i>F</i>, and then to call
<code>NaturalHomomorphism</code> with the arguments <i>G</i> and <i>F</i>.
For that, the data necessary to compute the homomorphism was stored in
<i>F</i> when <i>F</i> was constructed.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, factor structures are not treated in a special way,
in particular they do not store information about a homomorphism.
Instead, the more natural way is taken to construct the natural
homomorphism from <i>G</i> and <i>N</i> by <code>NaturalHomomorphismByNormalSubgroup</code>
if <i>N</i> is a normal subgroup of the group <i>G</i>,
or by <code>NaturalHomomorphismByIdeal</code> if <i>N</i> is an ideal in the ring <i>G</i>.
The factor <i>F</i> can then be accessed as the image of this homomorphism,
and of course <i>G</i> is the preimage and <i>N</i> is the kernel.
<p>
Note that <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 does not guarantee anything about the representation
of the factor <i>F</i>, it may be a permutation group or a polycyclically
presented group or another kind of group.
Also note that a natural homomorphism need not be surjective.
<p>
A consequence of this change is that <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 does <strong>not</strong> allow you to
construct a natural homomorphism from the groups <i>G</i> and <i>F</i>.
<p>
The other common type of homomorphism in <font face="Gill Sans,Helvetica,Arial">GAP</font> 3, ``operation
homomorphisms'', have been replaced (just a name change) by <strong>action
homomorphisms</strong>, which are handled in a similar fashion.  That is, an
action homomorphism is constructed from an acting group, an action
domain, and a function describing the operation.  The permutation
group arising by the induced action is then the image of this
operation homomorphism.
<p>
The <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 function <code>Operation</code> is still supported, under the name <code>Action</code>,
but from the original group and the result of <code>Action</code> it is not
possible to construct the action homomorphism.
<p>
<p>
<h2><a name="SECT015">9.15 Isomorphisms vs. Isomorphic Structures</a></h2>
<p><p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, a different representation of a group could be obtained by
calling <code>AgGroup</code> to get an isomorphic polycyclically presented group,
<code>PermGroup</code> to get an isomorphic permutation group, and so on.
The returned objects stored an isomorphism in the record component
<code>bijection</code>.
<p>
For the same reason as in&nbsp;<a href="CHAP009.htm#SECT014">Homomorphisms vs. Factor Structures</a>,
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 puts emphasis on the isomorphism,
and the isomorphic object in the desired representation can be accessed
as its image.
So you can call <code>IsomorphismPcGroup</code> or <code>IsomorphismPermGroup</code> in order
to get an isomorphism to a polycyclically presented group or a
permutation group, respectively, and then call <code>Image</code> to get the
isomorphic group.
<p>
Note that the image of an action homomorphism with trivial kernel is
also an isomorphic permutation group, but an action homomorphism need
not be surjective, since it may be easier to define it into the full
symmetric group.
<p>
Further note that in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, a usual application of isomorphisms to
polycyclically presented groups was to utilize the usually more
effective algorithms for solvable groups.  However, the new concept of
polycyclic generating systems in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 makes it possible to apply
these algorithms to arbitrary solvable groups, independent of the
representation.  For example, <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 can handle polycyclic
generating systems of solvable permutation groups.  So in many cases,
a change of the representation for efficiency reasons may be not
necessary any longer.
<p>
In general <code>IsomorphismFpGroup</code> will define a presentation on generators
chosen by the algorithm. The corresponding elements of the original
group can be obtained by the command
<pre>
gens:=List(GeneratorsOfGroup(Image(isofp)),i-&gt;PreImagesRepresentative(isofp,i));
</pre>
If a presentation in the given generators is needed, the command
<code>IsomorphismFpGroupByGenerators(</code><var>G</var><code>, </code><var>gens</var><code>)</code> will produce one.
<p>
<p>
<h2><a name="SECT016">9.16 Elements of Finitely Presented Groups</a></h2>
<p><p>
Strictly speaking, <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 did not support elements of finitely
presented groups.  Instead, the ``words in abstract generators'' of
the underlying free groups were (mis)used.  This caused problems
whenever calculations with elements were involved, the most obvious
ones being wrong results of element comparisons.  Also functions
that should in principle work for any group were not applicable to
finitely presented groups.  In effect, a finitely presented group had
to be treated in a special way in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3.
<p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 distinguishes free groups and their elements from finitely
presented groups and their elements.  Comparing two elements of a
finitely presented group will yield either the correct result or no
result at all.
<p>
Note that in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4, the arithmetic and comparison operations for
group elements do not depend on a context provided by a group that
contains the elements.  In particular, in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 it is not
meaningful to call <code>Order( </code><var>G</var><code>, </code><var>g</var><code> )</code> for a group <var>G</var> and an element
<var>g</var>.
<p>
<p>
<h2><a name="SECT017">9.17 Polynomials</a></h2>
<p><p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, polynomials were defined over a field. So a polynomial over
<code>GF(3)</code> was different from a polynomial over <code>GF(9)</code>, even if the
coefficients were exactly the same.
<p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 defines polynomials only over a characteristic. This makes it
possible for example to multiply a polynomial over <code>GF(3)</code> with a polynomial
over <code>GF(9)</code> without the need to convert the former to the larger field.
<p>
However it has an effect on the result of <code>DefaultRing</code> for polynomials:
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 the default ring for a polynomial was the polynomial ring of the
field over which the polynomial was defined. In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 no field is
associated, so (to avoid having to define the algebraic closure as the only
other sensible alternative) the default ring of a polynomial is the
<code>DefaultRing</code> of its coefficients.
<p>
This has an effect on <code>Factors</code>: If no ring is given, a polynomial is
factorized over its <code>DefaultRing</code> and so <code>Factors(</code><var>poly</var><code>)</code>
might return different results.
<p>
To be safe from this problem, if you are not working over prime fields,
rather call <code>Factors(</code><var>pring</var><code>,</code><var>poly</var><code>)</code> with the appropriate polynomial ring
and change your code accordingly.
<p>
<p>
<h2><a name="SECT018">9.18 The Info Mechanism</a></h2>
<p><p>
Sometimes it is useful to get information about the progress of a
calculation.
Many <font face="Gill Sans,Helvetica,Arial">GAP</font> functions contain statements to display such information
under certain conditions.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, these statements were calls to functions such as
<code>InfoGroup1</code> or <code>InfoGroup2</code>, and if the user assigned <code>Print</code> to
these variables then this had the effect to switch on the printing of
information.
<code>InfoGroup2</code> was used for more detailed information than <code>InfoGroup1</code>.
One could switch off the printing again by assigning <code>Ignore</code> to the
variables, and <code>Ignore</code> was also the default value.
<p>
<font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 uses one function <code>Info</code> for the same purpose,
which is a function that takes as first argument an <strong>info class</strong> such as
<code>InfoGroup</code>, as second argument an <strong>info level</strong>, and the print statements
as remaining arguments.
The level of an info class <var>class</var> is set to <var>level</var> by calling
<code>SetInfoLevel( </code><var>class</var><code>, </code><var>level</var><code> )</code>.
An <code>Info</code> statement is printed only if its second argument is smaller than
or equal to the current info level.
For example,
<pre>
gap&gt; test:= function( obj )
&gt; Info( InfoGroup, 2, "This is useful, isn't it?" );
&gt; return obj;
&gt; end;;
gap&gt; test( 1 );
1
gap&gt; SetInfoLevel( InfoGroup, 2 );
gap&gt; test( 1 );
#I  This is useful, isn't it?
1
</pre>
<p>
As in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, if an info statement is ignored then its arguments are
not evaluated.
<p>
<p>
<h2><a name="SECT019">9.19 Debugging</a></h2>
<p><p>
<a name = "I20"></a>

<a name = "I21"></a>

<a name = "I22"></a>

If <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 runs into an error or is interrupted,
it enters a break loop.
The command <code>Where( </code><var>number</var><code> )</code>, which replaces <code>Backtrace</code> of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3,
can be used to display <var>number</var> lines of information about the current
function call stack.
<p>
As in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, access is only possible to the variables of the current
level in the function stack,
but in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 the function <code>DownEnv</code>, with a positive or negative
integer as argument, permits one to step down or up in the
stack.
<p>
When interrupting, the first line printed by <code>Where</code> actually may be
one level higher, as the following example shows
<pre>
gap&gt; OnBreak := function() Where(0); end;; # eliminate back-tracing on
gap&gt;                                       # entry to break loop
gap&gt; test:= function( n )
&gt;    if n &gt; 3 then Error( "!\n" ); fi; test( n+1 ); end;;
gap&gt; test( 1 );
Error, !
Entering break read-eval-print loop ...
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk&gt; Where();
 called from
test( n + 1 ); called from
test( n + 1 ); called from
test( n + 1 ); called from
&lt;function&gt;( &lt;arguments&gt; ) called from read-eval-loop
brk&gt; n;
4
brk&gt; DownEnv();
brk&gt; n;
3
brk&gt; Where();  
 called from
test( n + 1 ); called from
test( n + 1 ); called from
&lt;function&gt;( &lt;arguments&gt; ) called from read-eval-loop
brk&gt; DownEnv( 2 );
brk&gt; n;
1
brk&gt; Where();     
 called from
&lt;function&gt;( &lt;arguments&gt; ) called from read-eval-loop
brk&gt; DownEnv( -2 );
brk&gt; n;
3
brk&gt; quit;
gap&gt; OnBreak := Where;; # restore OnBreak to its default value
</pre>
<p>
For purposes of debugging, it can be helpful sometimes, to see what
information is stored within an object. In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 this was possible using
<code>RecFields</code> because the objects in question were represented via records.
For component objects, <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 permits the same by
<code>NamesOfComponents( </code><var>object</var><code> )</code>, which will list all components present.
<p>
<p>
<h2><a name="SECT020">9.20 Compatibility Mode</a></h2>
<p><p>
For users who want to use <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 code with as little changes as
possible, a compatibility mode is provided by <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
This mode must be turned on explicitly by the user.
<p>
It should be noted that this compatibility mode has not been tested
thoroughly.
<p>
The compatibility mode can be turned on by loading some of the following
files with <code>ReadLib</code>.
The different files address different aspects of compatibility.
<p>
<p>
<dl compact>
<dt><code>compat3a.g</code> <dd>
    makes some <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 function names available that were changed
    in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4,
    and provides code for some <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 features that were
    deliberately left out from the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 library.
    For example,
    almost all variable names concerning character theory that are
    mentioned in the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 manual,
    such as <code>CharTable</code> and <code>SubgroupFusions</code>,
    are available after <code>compat3a.g</code> has been read;
    the only exceptions are names of operations records.
<p>
<dt><code>compat3b.g</code> <dd>
    implements the availability of ``components'' of domains;
    besides components that have no meaning for the rest of the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4
    library, such as <code></code><var>D</var><code>.myInfo</code>, there are components associated to
    attributes; for example <code></code><var>D</var><code>.size</code> is redirected to the call of the
    attribute <code>Size</code>, <code>IsBound( </code><var>D</var><code>.size )</code> to the call of its tester,
    and <code></code><var>D</var><code>.size:= </code><var>val</var><code></code> to the call of its setter.
    (An important special case is the component <code>operations</code>, see below.)
<p>
<dt><code>compat3c.g</code> <dd>
    permits you to implement your own elements represented as records,
    and using operations records to provide a <code>Print</code> method and
    the basic arithmetic operations.
    When using operations records, it is probably a good idea to
    use <strong>immutable</strong> operations records; for example, if the results
    of arithmetic operations are records with operations records then
    this avoids to create shallow copies of the operations records 
    in the call to <code>Immutable</code> for the results.
</dl>
<p>
The following features are accessible only via starting <font face="Gill Sans,Helvetica,Arial">GAP</font> with
the command line option <code>-O</code> and may damage some features of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4
permanently for the current session. 
<p>
 With this option, also the files listed above are read automatically.
<p>
<p>
<dl compact>
<dt><code>compat3d.g</code> <dd>
    provides some <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 functions like <code>Domain</code>, simulates the
    <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 behaviour of <code>IsString</code> (to convert a list to string
    representation if possible), and replaces <code>fail</code> by <code>false</code>;
    these changes destroy parts of the functionality of <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4.
</dl>
<p>
Some words concerning the simulation of operations records may be
necessary.
<p>
The operations records of the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 library, such as <code>DomainOps</code>
and <code>GroupOps</code>, are available <strong>only</strong> for access to their components,
whose values are <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 operations; for example, the value of both
<code>DomainOps.Size</code> and <code>GroupOps.Size</code> is the operation <code>Size</code>.  So it
is <strong>not</strong> safely possible to delegate from a <code>Size</code> method in another
operations record to <code>DomainOps.Size</code>.  Also it is not possible to
change these predefined operations records.
<p>
If one wants to install individual methods for a given object <var>obj</var>
via the mechanism of operations records then one can construct a new
operations record with <code>OperationsRecord</code>, assign the desired methods
to components of this record, and then assign the operations record to
<code></code><var>obj</var><code>.operations</code>.  Whenever an operation that is associated with a
component <var>nam</var> of the operations record is called with <var>obj</var> as first
argument, the value of <var>nam</var> is chosen as the method.
<p>
In the case of the binary operations <code>=</code>, <code>&lt;</code>, <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>,
<code>Comm</code>, and <code>LeftQuotient</code>,
this also happens if <var>obj</var> is the right-hand argument.
As in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, if both arguments of one of the above binary operations
have operations records containing a function for this operation,
then the function in the operations record of the right-hand argument
is chosen.
<p>
We give a small example how the compatibility mode works.
<p>
Suppose we want to deal with new objects that are derived from known
field elements by distorting their multiplication.  Namely, let <i>a</i>&#8242;
and <i>b</i>&#8242; be the new objects corresponding to the field elements <i>a</i>,
<i>b</i>, and define <i>a</i>&#8242;* <i>b</i>&#8242; = <i>a</i> <i>b</i> &#8722; <i>a</i> &#8722; <i>b</i> + 2.
<p>
In <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, this problem was solved by representing each new object
by a record that stored the corresponding ``old'' object and an
operations record, where the latter was a record containing the
functions applicable to the new object.  After the library file
<code>compat3c.g</code> has been read, we can use this construction of the
operations record and of the new objects.  Note that operations
records must be created with the function <code>OperationsRecord</code> (this was
also the norm in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3), starting with an empty record would not work.
For our intended application, we thus start with the following two
lines of code.
<p>
<pre>
gap&gt; ReadLib( "compat3c.g" );
gap&gt; MyOps:= OperationsRecord( "MyOps" );; 
HasMyOps := NewFilter( "HasMyOps" );
</pre>
<p>
In order to make the translation from <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3 code to <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4
easier, <font face="Gill Sans,Helvetica,Arial">GAP</font> prints the definition of filters associated with
operations records and the method installations for operations
corresponding to components of the operations records.  The output
line printed by <font face="Gill Sans,Helvetica,Arial">GAP</font> after the call of <code>OperationsRecord</code> is one
such case.
<p>
Now we add our multiplication function to the operations record,
and again <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 prints a translation to <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 code.
<p>
<pre>
gap&gt; MyOps.\* := function( a, b )
&gt;        return rec( x:= a.x * b.x - a.x - b.x + 2,
&gt;                    operations := MyOps );
&gt;    end;;
# If the following method installation matches the requirements
# of the operation `PROD' then `InstallMethod' should be used.
# It might be useful to replace the rank `SUM_FLAGS' by `0'.
InstallOtherMethod( PROD,
    "for object with `MyOps' as first argument",
    true,
    [ HasMyOps, IsObject ], SUM_FLAGS,
    MyOps.\* );

# For binary infix operators, a second method is installed
# for the case that the object with `MyOps' is the right operand;
# since this case has higher priority in GAP 3, the method is
# installed with higher rank `SUM_FLAGS + 1'.
InstallOtherMethod( PROD,
    "for object with `MyOps' as second argument",
    true,
    [ IsObject, HasMyOps ], SUM_FLAGS + 1,
    MyOps.\* );
</pre>
<p>
Let us look how this installation works.
<p>
<pre>
gap&gt; a:= rec( x:= 3, operations:= MyOps );
rec( x := 3, operations := MyOps )
gap&gt; b:= rec( x:= 5, operations:= MyOps );
rec( x := 5, operations := MyOps )
gap&gt; a * b;
rec( x := 9, operations := MyOps )
</pre>
<p>
(In more complicated cases, we might run into problems, but this was
already the case in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3.  For example, suppose we want to support
the multiplication of two operands having different operations
records; then it is not clear which of the two multiplication
functions is to be chosen, and in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3, the only way out was to
change the multiplication functions, in order to make them aware of
such situations.)
<p>
If we are now interested to translate the code to <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 in the
sense that no compatibility mode is needed, we can use what <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4
has printed above.  (The same example is dealt with in Chapter&nbsp;<a href="../prg/CHAP006.htm">An Example -- Designing Arithmetic Operations</a> of ``Programming in
GAP''.)
<p>
The objects will no longer be records with <code>operations</code> component.
Instead of records we may use so-called component objects
with record-like access to components, 
and instead of the <code>operations</code> component, we give the objects a
type that has the filter <code>HasMyOps</code> set.
<pre>
HasMyOps := NewFilter( "HasMyOps" );
MyType := NewType( NewFamily( "MyFamily" ),
                   HasMyOps and IsComponentObjectRep );
</pre>
(More about families and representations in this context can be found
in the chapter of ``Programming in GAP'' mentioned above.)
<p>
The next step is to write a function that creates a new object.
It may look as follows.
<pre>
MyObject := function( val )
    return Objectify( MyType, rec( x:= val ) );
end;
</pre>
<p>
The multiplication function shall return an object with the
filter <code>HasMyOp</code>, so we change it as follows.
<pre>
gap&gt; MyMult := function( a, b )                          
&gt;        return MyObject( x:= a!.x * b!.x - a!.x - b!.x + 2 );
&gt;    end;; 
</pre>
Note that the component access for these objects
works via <code>!.</code> instead of <code>.</code>;
further note that no operations record needs to appear here,
the filter takes its role.
<p>
Finally, we install the multiplication for at least one argument
with the new filter, as had been printed by <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 in the
session shown above.
<pre>
InstallOtherMethod( PROD,
    "for object with `MyOps' as first argument",
    true,
    [ HasMyOps, IsObject ], 0,
    MyMult );

InstallOtherMethod( PROD,
    "for object with `MyOps' as second argument",
    true,
    [ IsObject, HasMyOps ], 1,
    MyMult );
</pre>
And now the example works (again).
<pre>
gap&gt; a:= MyObject( 3 );
&lt;object&gt;
gap&gt; b:= MyObject( 5 );
&lt;object&gt;
gap&gt; a * b;
&lt;object&gt;
gap&gt; last!.x
9
</pre>
<p>
We may install a method to print our objects in a nice way;
we could have done this for the operations record <code>MyOps</code>
in the compatibility mode,
the printed output would look similar to the following.
<pre>
InstallOtherMethod( PRINT_OBJ,
    "for object with `MyOps' as first argument",
    true,
    [ HasMyOps ], 0,
    function( obj ) Print( "MyObject( ", obj!.x, " )" ); end );
</pre>
<p>
Now the example behaves as follows.
<pre>
gap&gt; a;  b;  a * b;
MyObject( 3 )
MyObject( 5 )
MyObject( 9 )
</pre>
<p>
Maybe now we want to improve the installation.
The multiplication function we want to use is apparently
thought only for the case that <strong>both</strong> operands have
the filter <code>HasMyOps</code> (and a component <code>x</code>).
So it is reasonable to replace the two methods for
the multiplication by one method for which both arguments
are required to have the filter.
<pre>
InstallOtherMethod( PROD,
    "for two objects with `MyOps'",
    true,
    [ HasMyOps, HasMyOps ], 0,
    MyMult );
</pre>
<p>
At first sight, the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 approach seems to be much more
complicated.
But the last example shows that in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4,
each method can be installed more specifically for the appropriate
situation.
Moreover, it is for example possible to install a method
for the multiplication of an integer and a <code>HasMyOps</code> object;
note that --contrary to the situation in <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;3--
such a method is independent from already existing methods
in the sense that these need not be changed when
new functionality is added.
<p>
Another example that uses this part of the compatibility mode can be
found in the file <code>tst/compat3.tst</code> of the <font face="Gill Sans,Helvetica,Arial">GAP</font>&nbsp;4 distribution.
<p>
<p>
[<a href="../index.htm">Top</a>] [<a href = "chapters.htm">Up</a>] [<a href ="CHAP008.htm">Previous</a>] [<a href ="CHAP010.htm">Next</a>] [<a href = "theindex.htm">Index</a>]
<P>
<font face="Gill Sans,Helvetica,Arial">GAP 4 manual<br>December 2008
</font></body></html>