Skip to content

Commit

Permalink
renamings: julia_to_gap -> GapObj
Browse files Browse the repository at this point in the history
- rename `julia_to_gap_internal` -> `GapObj_internal`
- rename `julia_to_gap` -> `GapObj`
- use `GapObj` instead of `GAP.GapObj` where appropriate
- adjust the documentation:
  - change some examples that used `julia_to_gap` and would not be correct
    if we replace it by `GapObj`
  - change formulations which relied on the distinction between
    the function `julia_to_gap` and the type/constructor `GapObj`
  - move some parts of docstrings and add cross-references such that
    the documentation fits to the new situation that there is no
    `julia_to_gap` anymore
    (I hope that Documenter.jl will keep the current behaviour that we
    can have two docstrings for `GapObj`, an unqualified one and
    a qualified one, which can appear in different places of the manual.)
  • Loading branch information
ThomasBreuer committed Sep 6, 2024
1 parent b2006ab commit b9acad3
Show file tree
Hide file tree
Showing 22 changed files with 222 additions and 227 deletions.
2 changes: 1 addition & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
simpler and safer and
- restrict the necessity to create dictionaries to situations where
recursive conversions make sense.
For that, the function `julia_to_gap_internal`, the macro `GAP.@install`,
For that, the function `GAP.GapObj_internal`, the macro `GAP.@install`,
and the type `GapCacheDict` were introduced.

## Version 0.11.1 (released 2024-06-06)
Expand Down
5 changes: 3 additions & 2 deletions docs/src/conversion.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ For a few types of objects, such conversions are unavoidable,
see [Automatic GAP-to-Julia and Julia-to-GAP Conversions](@ref).
In all other situations,
the conversions between GAP objects and corresponding Julia objects
can be performed using [`gap_to_julia`](@ref) and [`julia_to_gap`](@ref),
can be performed using [`gap_to_julia`](@ref) and
[`GapObj(x, cache::GapCacheDict = nothing; recursive::Bool = false)`](@ref),
see [Explicit GAP-to-Julia and Julia-to-GAP Conversions](@ref), respectively.

For convenience, also constructor methods are provided,
Expand Down Expand Up @@ -46,7 +47,7 @@ The exceptions are as follows.

```@docs
gap_to_julia
julia_to_gap
GapObj(x, cache::GapCacheDict = nothing; recursive::Bool = false)
```

## Constructor Methods for GAP-to-Julia Conversions
Expand Down
4 changes: 2 additions & 2 deletions docs/src/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ julia> Vector{Vector{Int}}(cf)
Next let us investigate the operation of the group on the 48 points.

```jldoctest rubik
julia> orbs = GAP.Globals.Orbits(cube, GAP.GapObj(1:48))
julia> orbs = GAP.Globals.Orbits(cube, GapObj(1:48))
GAP: [ [ 1, 3, 17, 14, 8, 38, 9, 41, 19, 48, 22, 6, 30, 33, 43, 11, 46, 40, 24, 27, 25, 35, 16, 32 ], [ 2, 5, 12, 7, 36, 10, 47, 4, 28, 45, 34, 13, 29, 44, 20, 42, 26, 21, 37, 15, 31, 18, 23, 39 ] ]
julia> length(orbs)
Expand Down Expand Up @@ -315,7 +315,7 @@ For this purpose we introduce a free group and a homomorphism of it
onto the cube group.

```jldoctest rubik
julia> f = GAP.Globals.FreeGroup(GAP.GapObj(["t", "l", "f", "r", "e", "b"], recursive = true))
julia> f = GAP.Globals.FreeGroup(GapObj(["t", "l", "f", "r", "e", "b"], recursive = true))
GAP: <free group on the generators [ t, l, f, r, e, b ]>
julia> fhom = GAP.Globals.GroupHomomorphismByImages(f, cube)
Expand Down
4 changes: 2 additions & 2 deletions docs/src/other.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,10 @@ regarding the mutability of the result
but here we have to choose one behaviour for the Julia function.

```jldoctest
julia> l = GAP.julia_to_gap( [ 1, 3, 7, 15 ] )
julia> l = GapObj( [ 1, 3, 7, 15 ] )
GAP: [ 1, 3, 7, 15 ]
julia> m = GAP.julia_to_gap( [ 1 2; 3 4 ] )
julia> m = GapObj( [ 1 2; 3 4 ] )
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
julia> length( l )
Expand Down
8 changes: 4 additions & 4 deletions pkg/JuliaInterface/gap/JuliaInterface.gd
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ DeclareAttribute( "JuliaPointer", IsJuliaWrapper );
#! <Julia module GAP>
#! gap> IsJuliaModule( Julia.GAP );
#! true
#! gap> Julia.GAP.julia_to_gap;
#! <Julia: julia_to_gap>
#! gap> JuliaFunction( "julia_to_gap", "GAP" ); # the same function
#! <Julia: julia_to_gap>
#! gap> Julia.GAP.gap_to_julia;
#! <Julia: gap_to_julia>
#! gap> JuliaFunction( "gap_to_julia", "GAP" ); # the same function
#! <Julia: gap_to_julia>
#! @EndExampleSession
DeclareCategory( "IsJuliaModule", IsJuliaWrapper and IsRecord );

Expand Down
16 changes: 8 additions & 8 deletions pkg/JuliaInterface/gap/convert.gd
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
#! On the &Julia; side, there is usually no need for a wrapper,
#! as (thanks to the shared garbage collector)
#! most &GAP; objects are valid &Julia; objects of type
#! <C>GAP.GapObj</C>.
#! <C>GapObj</C>.
#! The exception to that rule are immediate &GAP; objects,
#! more on that in the next section.
#! </Item>
Expand Down Expand Up @@ -84,7 +84,7 @@
#! <Ref Chap="Integers" BookName="ref"/> in the &GAP; Reference Manual.
#! Since these are not valid pointers, &Julia; cannot treat them like other
#! &GAP; objects, which are simply &Julia; objects of type
#! <C>GAP.GapObj</C>.
#! <C>GapObj</C>.
#! Instead, a conversion is unavoidable, at least when immediate objects
#! are passed as stand-alone arguments to a function.
#! <P/>
Expand Down Expand Up @@ -135,7 +135,7 @@
#! &Julia; function wrapper to &Julia; function,
#! </Item>
#! <Item>
#! other &GAP; objects to <C>GAP.GapObj</C>.
#! other &GAP; objects to <C>GapObj</C>.
#! </Item>
#! </List>
#!
Expand All @@ -156,7 +156,7 @@
#! &Julia; <C>false</C> to &GAP; <K>false</K>,
#! </Item>
#! <Item>
#! <C>GAP.GapObj</C> to <C>Obj</C>,
#! <C>GapObj</C> to <C>Obj</C>,
#! </Item>
#! <Item>
#! other &Julia; objects to &Julia; object wrapper.
Expand All @@ -169,7 +169,7 @@
#! <Ref Func="GAPToJulia"/> and
#! <Ref Constr="JuliaToGAP" Label="for IsObject, IsObject"/>.
#! In &Julia;, conversion is done via <C>gap_to_julia</C> and
#! <C>julia_to_gap</C>.
#! <C>GapObj</C>.
#!
#! <E>Conversion from &GAP; to &Julia;</E>
#!
Expand Down Expand Up @@ -289,7 +289,7 @@
#! of nested objects.
#! Various methods for this constructor then take care of input validation
#! and the actual conversion, either by delegating to the &Julia; function
#! <C>julia_to_gap</C>
#! <C>GapObj</C>
#! (which takes just one or two arguments and chooses the &GAP; filters of
#! its result depending on the &Julia; type),
#! or by automatic conversion.
Expand Down Expand Up @@ -370,7 +370,7 @@
#!
#! <ManSection>
#! <Func Name="Julia.GAP.Obj" Arg="juliaobj[, recursive]"/>
#! <Func Name="Julia.GAP.GapObj" Arg="juliaobj[, recursive]"/>
#! <Func Name="Julia.GapObj" Arg="juliaobj[, recursive]"/>
#! <Returns>a &GAP; object</Returns>
#! <Description>
#! The &Julia; constructor <Ref Func="Julia.GAP.Obj"/> takes an object
Expand Down Expand Up @@ -403,7 +403,7 @@
#! via suitable methods for <Ref Func="Julia.GAP.Obj"/>.
#! <P/>
#! If one is sure that the result of the conversion to &GAP; is not an
#! immediate &GAP; object then one can call <Ref Func="Julia.GAP.GapObj"/>
#! immediate &GAP; object then one can call <Ref Func="Julia.GapObj"/>
#! instead of <Ref Func="Julia.GAP.Obj"/>.
#! </Description>
#! </ManSection>
Expand Down
12 changes: 6 additions & 6 deletions pkg/JuliaInterface/gap/convert.gi
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
InstallMethod(JuliaToGAP, ["IsInt", "IsJuliaObject"],
function(filter, obj)
if Julia.isa(obj, Julia.Base.Integer) then
return Julia.GAP.julia_to_gap(obj);
return Julia.GapObj(obj);
fi;
Error("<obj> must be a Julia integer");
end);
Expand All @@ -22,7 +22,7 @@ end);
InstallMethod(JuliaToGAP, ["IsRat", "IsJuliaObject"],
function(filter, obj)
if Julia.isa(obj, Julia.Base.Integer) or Julia.isa(obj, Julia.Base.Rational) then
return Julia.GAP.julia_to_gap(obj);
return Julia.GapObj(obj);
fi;
Error("<obj> must be a Julia integer or rational");
end);
Expand All @@ -38,7 +38,7 @@ end);
InstallMethod(JuliaToGAP, ["IsFloat", "IsJuliaObject"],
function(filter, obj)
if Julia.isa(obj, Julia.Base.AbstractFloat) then
return Julia.GAP.julia_to_gap(obj);
return Julia.GapObj(obj);
fi;
Error("<obj> must be a Julia float");
end);
Expand All @@ -54,10 +54,10 @@ end);
InstallMethod(JuliaToGAP, ["IsChar", "IsJuliaObject"],
function(filter, obj)
if Julia.isa(obj, Julia.Base.Char) then
return Julia.GAP.julia_to_gap(obj);
return Julia.GapObj(obj);
elif Julia.isa(obj, Julia.Base.Int8) or
Julia.isa(obj, Julia.Base.UInt8) then
return CharInt( Julia.GAP.julia_to_gap(obj) );
return CharInt( Julia.GapObj(obj) );
fi;

Error("<obj> must be a Julia Char or Int8 or UInt8");
Expand Down Expand Up @@ -119,7 +119,7 @@ InstallMethod(JuliaToGAP, ["IsString", "IsJuliaObject"],
function(filter, obj)
if Julia.isa(obj, Julia.Base.AbstractString) or
Julia.isa(obj, Julia.Base.Symbol) then
return Julia.GAP.julia_to_gap(obj);
return Julia.GapObj(obj);
fi;
Error("<obj> must be a Julia string or symbol");
end);
Expand Down
6 changes: 3 additions & 3 deletions pkg/JuliaInterface/gap/juliahelp.g
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@
#! &Julia; functions belong to &Julia; modules.
#! Many &Julia; functions can be accessed only relative to their modules,
#! and then also the help requests work only for the qualified names.
#! For example, <C>?Julia:GAP.julia_to_gap</C> yields the description
#! of the &Julia; function <C>julia_to_gap</C> that is defined in the
#! For example, <C>?Julia:GAP.wrap_rng</C> yields the description
#! of the &Julia; function <C>wrap_rng</C> that is defined in the
#! &Julia; module <C>GAP</C>,
#! whereas no match is found for the input <C>?Julia:julia_to_gap</C>.
#! whereas no match is found for the input <C>?Julia:wrap_rng</C>.
#! </Item>
#! </List>
#! @EndChunk
Expand Down
6 changes: 3 additions & 3 deletions pkg/JuliaInterface/tst/convert.tst
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,11 @@ gap> Julia.GAP.Obj( list );
[ 1, 2, 3 ]

## ranges
gap> Julia.GAP.julia_to_gap( JuliaEvalString( "1:3" ) );
gap> Julia.GapObj( JuliaEvalString( "1:3" ) );
[ 1 .. 3 ]
gap> Julia.GAP.julia_to_gap( JuliaEvalString( "1:2:5" ) );
gap> Julia.GapObj( JuliaEvalString( "1:2:5" ) );
[ 1, 3 .. 5 ]
gap> Julia.GAP.julia_to_gap( JuliaEvalString( "3:2" ) );
gap> Julia.GapObj( JuliaEvalString( "3:2" ) );
[ ]
gap> Julia.GAP.Obj( JuliaEvalString( "1:3" ) );
[ 1 .. 3 ]
Expand Down
4 changes: 2 additions & 2 deletions src/adapter.jl
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ Base.copy(rng::MersenneTwister) = MersenneTwister(state=MersenneTwisterState(Glo
Random.rand(rng::AbstractGAPRNG, x::Random.SamplerTrivial{<:Obj}) = Globals.Random(rng.ptr, x[])

Random.rand(rng::AbstractGAPRNG, x::Random.SamplerTrivial{<:AbstractUnitRange}) =
Globals.Random(rng.ptr, julia_to_gap(first(x[])), julia_to_gap(last(x[])))
Globals.Random(rng.ptr, GapObj(first(x[])), GapObj(last(x[])))

Random.Sampler(::Type{<:AbstractGAPRNG}, x::AbstractUnitRange, ::Random.Repetition) =
Random.SamplerTrivial(x)
Expand All @@ -464,7 +464,7 @@ for U in (Base.BitInteger64, Union{Int128,UInt128})
end

Random.Sampler(::Type{<:AbstractGAPRNG}, x::AbstractVector, ::Random.Repetition) =
Random.SamplerTrivial(julia_to_gap(x, recursive=false))
Random.SamplerTrivial(GapObj(x, recursive=false))


# The following bypasses GAP's redirection of `x^-1` to `InverseSameMutability(x)`.
Expand Down
4 changes: 2 additions & 2 deletions src/ccalls.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ be a useful escape hatch to access GAP functionality that is otherwise
impossible to difficult to reach. But in most typical scenarios it
should not be necessary to use it at all.
Instead, use `GAP.GapObj` or `GAP.Obj` for constructing GAP objects
Instead, use `GapObj` or `GAP.Obj` for constructing GAP objects
that correspond to given Julia objects,
and call GAP functions directly in the Julia session.
For example, executing `GAP.evalstr( "x:= []; Add( x, 2 )" )`
can be replaced by the Julia code `x = GAP.GapObj([]); GAP.Globals.Add(x, 2)`.
can be replaced by the Julia code `x = GapObj([]); GAP.Globals.Add(x, 2)`.
Note that the variable `x` in the former example lives in the GAP session,
i.e., it can be accessed as `GAP.Globals.x` after the call of `GAP.evalstr`,
whereas `x` in the latter example lives in the Julia session.
Expand Down
7 changes: 3 additions & 4 deletions src/constructors.jl
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
## Handle "conversion" to GAP.Obj and GAP.GapObj (may occur in recursions).
## Handle "conversion" to GAP.Obj and GapObj (may occur in recursions).
Obj(x::Obj) = x
GapObj(x::GapObj) = x

## Handle conversion of Julia objects to GAP objects
Obj(obj; recursive::Bool = false) = GapObj_internal(obj, nothing, recursive)::Obj
GapObj(obj; recursive::Bool = false) = GapObj_internal(obj, nothing, recursive)::GapObj

Obj(obj, recursive::Bool) = GapObj_internal(obj, nothing, recursive)::Obj
GapObj(obj, recursive::Bool) = GapObj_internal(obj, nothing, recursive)::GapObj
GapObj(obj, recursive::Bool) = GapObj_internal(obj, nothing, recursive)::Obj

## Conversion to gap integers
GapInt(x::Integer) = julia_to_gap(x)
GapInt(x::Integer) = GapObj(x)


"""
Expand Down
46 changes: 34 additions & 12 deletions src/julia_to_gap.jl
Original file line number Diff line number Diff line change
@@ -1,31 +1,53 @@
## Converters
"""
julia_to_gap(input, recursion_dict::GapCacheDict = nothing; recursive::Bool = false)
GapObj(input, recursion_dict::GapCacheDict = nothing; recursive::Bool = false)
GapObj(input, recursive::Bool = false)
One can use the type [`GapObj`](@ref) as a constructor,
in order to convert the julia object `input` to an appropriate GAP object.
If `recursive` is set to `true`, recursive conversion of nested Julia objects
(arrays, tuples, and dictionaries) is performed.
Convert a julia object `input` to an appropriate GAP object.
If `recursive` is set to `true`, recursive conversion on
arrays, tuples, and dictionaries is performed.
The input `recursion_dict` should never be set by the user, it is meant to keep egality
of input data, by converting equal data to identical objects in GAP.
# Examples
```jldoctest
julia> GAP.julia_to_gap(1//3)
julia> GapObj(1//3)
GAP: 1/3
julia> GAP.julia_to_gap("abc")
julia> GapObj("abc")
GAP: "abc"
julia> GAP.julia_to_gap([ [1, 2], [3, 4]])
julia> GapObj([1 2; 3 4])
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
julia> GapObj([[1, 2], [3, 4]])
GAP: [ <Julia: [1, 2]>, <Julia: [3, 4]> ]
julia> GAP.julia_to_gap([ [1, 2], [3, 4]], recursive = true)
julia> GapObj([[1, 2], [3, 4]], true)
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
julia> GapObj([[1, 2], [3, 4]], recursive = true)
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
```
Note that this conversion is *not* restricted to outputs that actually are
of type `GapObj`,
also GAP integers, finite field elements, and booleans can be created
by the constructor `GapObj`.
```jldoctest
julia> res = GapObj(42); res isa GapObj
false
julia> res isa GAP.Obj
true
```
The following `julia_to_gap` conversions are supported by GAP.jl.
The following `GapObj` conversions are supported by GAP.jl.
(Other Julia packages may provide conversions for more Julia objects.)
| Julia type | GAP filter |
Expand All @@ -46,9 +68,9 @@ The following `julia_to_gap` conversions are supported by GAP.jl.
| `UnitRange{T}`, `StepRange{T, S}` | `IsRange` |
| `Function` | `IsFunction` |
"""
julia_to_gap(x, cache::GapCacheDict = nothing; recursive::Bool = false) = GapObj_internal(x, cache, recursive)
GapObj(x, cache::GapCacheDict = nothing; recursive::Bool = false) = GapObj_internal(x, cache, recursive)

# The calls to `GAP.@install` install methods for `GapObj_internal`
# The calls to `GAP.@install` install methods for `GAP.GapObj_internal`
# so we must make sure it is declared before
function GapObj_internal end

Expand Down Expand Up @@ -226,7 +248,7 @@ end
## We have to do something only if recursive conversion is required,
## and if `obj` contains Julia subobjects;
## in this case, `obj` is a GAP list or record.
## An example of such an `obj` is `GAP.julia_to_gap([[1]])`.
## An example of such an `obj` is `GapObj([[1]])`.
function GapObj_internal(
obj::GapObj,
recursion_dict::GapCacheDict,
Expand Down
8 changes: 4 additions & 4 deletions src/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,9 @@ macro wrap(ex)
# type annotations -> split and decide what to do
var = x.args[1]
typeannot = x.args[2]
if typeannot in [:GapObj, :(GAP.GapObj)]
# the lhs has no type annotation, rhs gets wrapped in `GAP.GapObj(...)::GAP.GapObj`
(var, :(GAP.GapObj($var)::GAP.GapObj))
if typeannot in [:GapObj, :(GapObj)]
# the lhs has no type annotation, rhs gets wrapped in `GapObj(...)::GapObj`
(var, :(GapObj($var)::GapObj))
elseif typeannot == :(GAP.Obj)
# the lhs has no type annotation, rhs gets wrapped in `GAP.Obj(...)::GAP.Obj`
(var, :(GAP.Obj($var)::GAP.Obj))
Expand All @@ -403,7 +403,7 @@ macro wrap(ex)
]
lhsargs = map(first, tempargs)
rhsargs = map(last, tempargs)

# the "outer" part of the body
body = MacroTools.@qq begin
global $newsym
Expand Down
Loading

0 comments on commit b9acad3

Please sign in to comment.