Use the macros `@gapattribute` and `@gapwrap` in order to get access
to GAP's "tester" and "setter" functions for its attributes.
This had been suggested in issue #128.
The code requires the changes from the pull request oscar-system/GAP.jl/pull/647.
The branch has the same name as that of the current pull request.
(There are more places where the macros can be applied.
First we should agree on the setup, see below.)
- The names of the tester/setter functions on the Julia side should
perhaps be changed:
Would `has_derived_subgroup` look better than `hasderived_subgroup`?
(This is something to be changed in GAP.jl.)
- Some of the functions in `Oscar/src/Groups` (`conjugacy_classes`,
`conjugacy_classes_subgroups`, `conjugacy_classes_maximal_subgroups`)
cannot be handled by the current `@gapattribute`,
because they involve several calls to some function in `GAP.Globals`.
The point is that the names of the tester and setter are "guessed" from
the body of the given (getter) function.
If there is just one call to a function in `GAP.Globals` then this is safe,
otherwise we have to find some heuristic that is easy to document.
- In a few cases (`exponent`), I have added individual `import` statements
because the current `@gapattribute` does not strip module names from the
beginning of the function name; we could change the macro in order to
avoid these `import` statements.
- In order to keep the docstrings of the functions handled by `@gapattribute`,
I did not see a better way than to move the code above the docstring.
- Another point for the documentation is how to document the testers and
setters. We could show three-line descriptions of the kind
```
isperfect(G::Group)
hasisperfect(G::Group)
setisperfect(G::Group, val)
```
in all relevant places, instead of just the first of these lines.
Or would this become too long?
(I have extended the `export` lists by the testers and setters.
Is this o.k.?)
- I have changed the behaviour of the functions only in one place.
Up to now, `trivial_subgroup` constructed just a group on the Julia side,
without calling GAP's `GAP.Globals.TrivialSubgroup`, but now the attribute
on the GAP side is called, due to `@gapattribute`.
The side-effect is that now the return value of `trivial_subgroup` has
an empty list of generators,
whereas this list contained the identity element before.
This change seems to be no problem for the tests,
but perhaps it has to be documented that the result of `gens` may be empty.
The conceptual question is whether we really want to change `trivial_subgroup`
such that the corresponding GAP function gets called.
We can take the viewpoint that the Julia side should better avoid work on
the GAP side where possible (one can create a trivial subgroup in Oscar
without "help from GAP"),
or we can argue that the GAP side should better be kept informed about
knowledge that has been computed on the Julia side.
Note that in the cases of boolean values,
the stored GAP attributes really serve as caches;
but already for a group order stored in GAP,
a conversion may be necessary before the value can be used on the Julia side.
One "border case" is `ispgroup`:
Its return value is a tuple not just the boolean value that is stored on the
GAP side.
Any access from Oscar's `ispgroup` creates a new Julia object.
- The following two inconsistencies should be dealt with in other pull requests:
`center` and `ischaracteristic` are known in (and imported from) Hecke,
but Oscar.Groups defines `centre` and `ischaracteristic_subgroup`.