# 45.4 Comparisons of Records

`rec1 = rec2`
`rec1 < rec2`

The equality operator `=` returns `true` if the record rec1 is equal to the record rec2 and `false` otherwise. The inequality operator `<` returns `true` if the record rec1 is not equal to rec2 and `false` otherwise.

Usually two records are considered equal, if for each component of one record the other record has a component of the same name with an equal value and vice versa. You can also compare records with other objects, they are of course different, unless the record has a special comparison function (see below) that says otherwise.

```    gap> rec( a := 1, b := 2 ) = rec( b := 2, a := 1 );
true
gap> rec( a := 1, b := 2 ) = rec( a := 2, b := 1 );
false
gap> rec( a := 1 ) = rec( a := 1, b := 2 );
false
gap> rec( a := 1 ) = 1;
false ```

However a record may contain a special `operations` record that contains a function that is called when this record is an operand of a comparison. The precise mechanism is as follows. If the operand of the equality operator `=` is a record, and if this record has an element with the name `operations` that is a record, and if this record has an element with the name `=` that is a function, then this function is called with the operands of `=` as arguments, and the value of the operation is the result returned by this function. In this case a record may also be equal to an object of another type if this function says so. It is probably not a good idea to define a comparison function in such a way that the resulting relation is not an equivalence relation, i.e., not reflexive, symmetric, and transitive. Note that there is no corresponding `<` function, because `left < right` is implemented as `not left = right`.

The following example shows one piece of the definition of residue classes, using record operations. Of course this is far from a complete implementation (see About Defining New Group Elements). Note that the `=` must be quoted, so that it is taken as an identifier (see Identifiers).

```    gap> ResidueClassOps := rec( );;
gap> ResidueClassOps.\= := function ( l, r )
>   return (l.modulus = r.modulus)
>     and (l.representative-r.representative) mod l.modulus = 0;
> end;;
gap> ResidueClass := function ( representative, modulus )
>   return rec(
>     representative := representative,
>     modulus        := modulus,
>     operations     := ResidueClassOps );
> end;;
gap> l := ResidueClass( 13, 23 );;
gap> r := ResidueClass( -10, 23 );;
gap> l = r;
true
gap> l = ResidueClass( 10, 23 );
false ```

`rec1 < rec2`
`rec1 <= rec2`
`rec1 rec2`
`rec1 = rec2`

The operators `<`, `<=`, , and `=` evaluate to `true` if the record rec1 is less than, less than or equal to, greater than, and greater than or equal to the record rec2, and to `false` otherwise.

To compare records we imagine that the components of both records are sorted according to their names. Then the records are compared lexicographically with unbound elements considered smaller than anything else. Precisely one record rec1 is considered less than another record rec2 if rec2 has a component with name name2 and either rec1 has no component with this name or `rec1.name2 < rec2.name2` and for each component of rec1 with name `name1 < name2` rec2 has a component with this name and `rec1.name1 = rec2.name1`. Records may also be compared with objects of other types, they are greater than anything else, unless the record has a special comparison function (see below) that says otherwise.

```    gap> rec( a := 1, b := 2 ) < rec( b := 2, a := 1 );
false    # they are equal
gap> rec( a := 1, b := 2 ) < rec( a := 2, b := 0 );
true    # the 'a' elements are compared first and 1 is less than 2
gap> rec( a := 1 ) < rec( a := 1, b := 2 );
true    # unbound is less than 2
gap> rec( a := 1 ) < rec( a := 0, b := 2 );
false    # the 'a' elements are compared first and 0 is less than 1
gap> rec( b := 1 ) < rec( b := 0, a := 2 );
true    # the 'a'-s are compared first and unbound is less than 2
gap> rec( a := 1 ) < 1;
false    # other objects are less than records ```

However a record may contain a special `operations` record that contains a function that is called when this record is an operand of a comparison. The precise mechanism is as follows. If the operand of the equality operator `<` is a record, and if this record has an element with the name `operations` that is a record, and if this record has an element with the name `<` that is a function, then this function is called with the operands of `<` as arguments, and the value of the operation is the result returned by this function. In this case a record may also be smaller than an object of another type if this function says so. It is probably not a good idea to define a comparison function in such a way that the resulting relation is not an ordering relation, i.e., not antisymmetric, and transitive. Note that there are no corresponding `<=`, , and `=` functions, since those operations are implemented as `not right < left`, `right < left`, and `not left < right` respectively.

The following example shows one piece of the definition of residue classes, using record operations. Of course this is far from a complete implementation (see About Defining New Group Elements). Note that the `<` must be quoted, so that it is taken as an identifier (see Identifiers).

```    gap> ResidueClassOps := rec( );;
gap> ResidueClassOps.\< := function ( l, r )
>   if l.modulus <> r.modulus  then
>     Error("<l> and <r> must have the same modulus");
>   fi;
>   return   l.representative mod l.modulus
>          < r.representative mod r.modulus;
> end;;
gap> ResidueClass := function ( representative, modulus )
>   return rec(
>     representative := representative,
>     modulus        := modulus,
>     operations     := ResidueClassOps );
> end;;
gap> l := ResidueClass( 13, 23 );;
gap> r := ResidueClass( -1, 23 );;
gap> l < r;
true    # 13 is less than 22
gap> l < ResidueClass( 10, 23 );
false    # 10 is less than 13 ```

GAP 3.4.4
April 1997