Basics
Accessing GAP from Julia
- Any global GAP variable and function can be accessed from Julia via the - GAP.Globalsobject; for example- GAP.Globals.Binomial(5,3). See Convenience adapters for dealing with GAP syntax beyond simple function calls.
- The - GAP.promptcommand can be used to switch to a GAP session that works like a regular GAP, except that leaving it (via- quit;or by pressing Ctrl-D) returns one to a Julia prompt. From the GAP prompt, one can access Julia variables via the- Juliaobject, for example- Julia.binomial(5,3). For more details on how to access Julia from GAP, please consult the manual of the GAP package JuliaInterface.
- Alternatively, one can start GAP in the traditional way, by executing a shell script. Such a script can be created in a location of your choice via - GAP.create_gap_sh. Note that one cannot switch from such a GAP session to the underlying Julia session and back.
GAP.Globals — ConstantGlobalsThis is a global object that gives access to all global variables of the current GAP session via getproperty and setproperty!.
Examples
julia> GAP.Globals.Size    # a global GAP function
GAP: <Attribute "Size">
julia> GAP.Globals.size    # there is no GAP variable with this name
ERROR: GAP variable size not bound
[...]
julia> hasproperty( GAP.Globals, :size )
false
julia> GAP.Globals.size = 17;
julia> hasproperty( GAP.Globals, :size )
true
julia> GAP.Globals.size
17
julia> GAP.Globals.UnbindGlobal(g"size")
julia> GAP.Globals.Julia   # Julia objects can be values of GAP variables
Main
GAP.evalstr — Functionevalstr(cmd::String)Let GAP execute the command(s) given by cmd; if an error occurs then report this error, otherwise if the last command has a result then return it, otherwise return nothing.
Examples
julia> GAP.evalstr( "1+2" )
3
julia> GAP.evalstr( "x:= []" )
GAP: [  ]
julia> GAP.evalstr( "y:= 2; Add( x, y )" )
julia> GAP.evalstr( "x" )
GAP: [ 2 ]
julia> GAP.evalstr( "Print( x )" )Note that screen outputs caused by evaluating cmd are not shown by evalstr; use evalstr_ex for accessing both the outputs and the return values of the command(s).
In general we recommend to avoid using evalstr, but it sometimes can 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 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 = 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.
GAP.evalstr_ex — Functionevalstr_ex(cmd::String)Assume that cmd consists of $n$ GAP statements, each terminated by ; or ;;. Let GAP execute these statements and return a GAP list of length $n$ that describes their results. Each entry of the return value is a GAP list of length 5, with the following meaning.
- The first entry is trueif the statement was executed successfully, andfalseotherwise.
- If the first entry is true, then the second entry is bound to the result of the statement if there was one, and unbound otherwise.
- The third entry is unbound if an error occured, trueif the statement ends in a double semicolon, andfalseotherwise.
- The fourth entry currently is always unbound.
- The fifth entry contains the captured output of the statement as a string. If there was no double semicolon then also the output of GAP.Globals.ViewObjapplied to the result value in the second entry, if any, is part of that string.
Examples
julia> GAP.evalstr_ex( "1+2" )        # error due to missing semicolon
GAP: [ [ false,,,, "" ] ]
julia> GAP.evalstr_ex( "1+2;" )       # one statement with return value
GAP: [ [ true, 3, false,, "3" ] ]
julia> GAP.evalstr_ex( "1+2;;" )      # the same with suppressed output
GAP: [ [ true, 3, true,, "" ] ]
julia> GAP.evalstr_ex( "x:= []; Add(x, 1);" )  # two valid commands
GAP: [ [ true, [ 1 ], false,, "[  ]" ], [ true,, false,, "" ] ]
julia> GAP.evalstr_ex( "1/0; 1+1;" )  # one error, one valid command
GAP: [ [ false,,,, "" ], [ true, 2, false,, "2" ] ]
julia> GAP.evalstr_ex( "Print(1);" )  # no return value but output
GAP: [ [ true,, false,, "1" ] ]
julia> GAP.evalstr_ex( "" )           # empty input
GAP: [  ]GAP.prompt — Functionprompt()Start a GAP prompt where you can enter GAP commands as in a regular GAP session. This prompt can be left as any GAP prompt by either entering quit; or pressing ctrl-D, which returns to the Julia prompt.
This GAP prompt allows to quickly switch between writing Julia and GAP code in a session where all data is shared.
GAP.Setup.create_gap_sh — Functioncreate_gap_sh(dstdir::String)Given a directory path, create three files in that directory:
- a shell script named gap.shwhich acts like thegap.shshipped with a regular GAP installation, but which behind the scenes launches GAP via Julia.
- two TOML files, Manifest.tomlandProject.toml, which are required bygap.shto function (they record the precise versions of GAP.jl and other Julia packages involved)
Accessing Julia from GAP
The GAP-Julia interface is fully bidirectional, so it is also possible to access all Julia functionality from GAP. To learn more about this, please consult the manual of the GAP package JuliaInterface.
Types
GAP.FFE — TypeFFEWrap a pointer to a GAP FFE ("finite field element") immediate object. This type is defined in the JuliaInterface C code.
Examples
julia> x = GAP.Globals.Z(3)
GAP: Z(3)
julia> typeof(x)
FFEGAP.GapObj — TypeGapObjThis is the Julia type of all those GAP objects that are not "immediate" (booleans, small integers, FFEs).
Examples
julia> typeof(GapObj([1, 2]))          # a GAP list
GapObj
julia> typeof(GapObj(Dict(:a => 1)))   # a GAP record
GapObj
julia> typeof( GAP.evalstr( "(1,2,3)" ) )  # a GAP permutation
GapObj
julia> typeof( GAP.evalstr( "2^64" ) )     # a large GAP integer
GapObj
julia> typeof( GAP.evalstr( "2^59" ) )     # a small GAP integer
Int64
julia> typeof( GAP.evalstr( "Z(2)" ) )     # a GAP FFE
FFE
julia> typeof( GAP.evalstr( "true" ) )     # a boolean
BoolNote that this is Julia's viewpoint on GAP objects. From the viewpoint of GAP, also the pointers to Julia objects are implemented as "non-immediate GAP objects", but they appear as Julia objects to Julia, not "doubly wrapped".
Examples
julia> GAP.evalstr( "Julia.Base" )
Base
julia> typeof( GAP.evalstr( "Julia.Base" ) )        # native Julia object
ModuleEquality of two GapObjs is defined by delegating to GAP's equality test. Since GAP does not define hash values for its objects, it cannot provide data for a nontrivial hash method for the type GapObj. This is because a hash method must satisfy the condition that a == b implies hash(a) == hash(b). The only universal way to guarantee that would be to define hash to be constant on objects of type GapObj, but this would lead to inefficient code. Therefore we decided to throw an error exception whenever hash is called with a GapObj. This implies that for example no nonempty object of the Julia type Set{GapObj} can be created.
One can use GapObj as a constructor, in order to convert Julia objects to GAP objects, see GapObj(x; recursive::Bool = false) for that.
GAP.Obj — TypeGAP.ObjThis is an alias for Union{GapObj,FFE,Int64,Bool}. This type union covers all types a "native" GAP object may have from Julia's viewpoint.
Moreover, it can be used as a constructor, in order to convert Julia objects to GAP objects, whenever a suitable conversion has been defined.
Recursive conversion of nested Julia objects (arrays, tuples, dictionaries) can be forced either by a second argument true or by the keyword argument recursive with value true.
Examples
julia> GAP.Obj(1//3)
GAP: 1/3
julia> GAP.Obj([1 2; 3 4])
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
julia> GAP.Obj([[1, 2], [3, 4]])
GAP: [ <Julia: [1, 2]>, <Julia: [3, 4]> ]
julia> GAP.Obj([[1, 2], [3, 4]], true)
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
julia> GAP.Obj([[1, 2], [3, 4]], recursive=true)
GAP: [ [ 1, 2 ], [ 3, 4 ] ]
julia> GAP.Obj(42)
42GAP.GapInt — TypeGapIntAny GAP integer object is represented in Julia as either a GapObj (if it is a "large" integer) or as an Int (if it is a "small" integer). This type union can be used to express this conveniently, e.g. when one wants to help type stability.
Note that also GAP's infinity and -infinity fit under this type (as do many other objects which are not numbers).