‣ IsJuliaObject ( obj ) | ( filter ) |
Returns: true
or false
The result is true
if and only if obj is a pointer to a Julia object.
gap> julia_fun:= JuliaEvalString( "sqrt" ); <Julia: sqrt> gap> IsJuliaObject( julia_fun ); true gap> julia_val:= julia_fun( 2 ); <Julia: 1.4142135623730951> gap> IsJuliaObject( julia_val ); true
However not every object living on the Julia side is in this filter. For example Julia booleans and small Int
values are directly translated to GAP booleans and small integers, while for Julia functions dedicated wrappers are used to improve efficiency and add features.
gap> JuliaEvalString( "x = 4" );; gap> Julia.x; 4 gap> IsJuliaObject( Julia.x ); false gap> IsJuliaObject( Julia.sqrt ); false
‣ IsJuliaWrapper ( obj ) | ( filter ) |
Returns: true
or false
If the component or positional object obj is in this filter then calling a Julia function with obj as an argument will not pass obj as an GapObj
, but instead its JuliaPointer
(2.1-3) value is passed, which must be a Julia object. This admits implementing high-level wrapper objects for Julia objects that behave just like the Julia objects when used as arguments in calls to Julia functions.
Objects in IsJuliaWrapper
should not be in the filter IsJuliaObject
(2.1-1).
‣ JuliaPointer ( obj ) | ( attribute ) |
is an attribute for GAP objects in the filter IsJuliaWrapper
(2.1-2). The value must be a Julia object.
‣ IsJuliaModule ( obj ) | ( filter ) |
Returns: true
or false
This filter is set in those GAP objects that represent Julia modules. Members of a Julia module can be accessed like record components.
gap> IsJuliaModule( Julia ); true gap> Julia.GAP; <Julia module GAP> gap> IsJuliaModule( Julia.GAP ); true gap> Julia.GAP.gap_to_julia; <Julia: gap_to_julia>
‣ JuliaEvalString ( string ) | ( function ) |
evaluates the string string in the current Julia session, in the Main
module, and returns Julia's return value.
gap> JuliaEvalString( "x = 2^2" ); # assignment to a variable in Julia 4 gap> JuliaEvalString( "x" ); # access to this variable 4
‣ JuliaIncludeFile ( filename[, module_name] ) | ( function ) |
Returns: nothing.
calls Julia's Base.include
with the strings filename (an absolute filename, as returned by Filename
(Reference: Filename)) and module_name (the name of a Julia module, the default is "Main"
). This means that the Julia code in the file with name filename gets executed in the current Julia session, in the context of the Julia module module_name.
‣ JuliaImportPackage ( pkgname ) | ( function ) |
Returns: true
or false
.
This function triggers the execution of an import
statement for the Julia package with name pkgname. It returns true
if the call was successful, and false
otherwise.
Note that we just want to load the package into Julia, we do not want to import variable names from the package into Julia's Main
module, because the Julia variables must be referenced relative to their modules if we want to be sure to access the correct values.
Why is this function needed?
Apparently libjulia
throws an error when trying to compile the package, which happens when some files from the package have been modified since compilation.
Thus GAP has to check whether the Julia package has been loaded successfully, and can then safely load and execute code that relies on this Julia package. In particular, we cannot just put the necessary import
statements into the relevant .jl
files, and then load these files with JuliaIncludeFile
(2.2-2).
Not all Julia syntax features are supported in GAP. For important ones, the interface provides GAP functions or helper functions written in Julia to use them in GAP. For example, CallJuliaFunctionWithCatch
(2.3-3) allows one to use Julia's try/catch statements.
Here is a selection of other workarounds for Julia syntax features.
Julia's RefValue
objects can be handled as follows. If x
is such an object then its value can be fetched with Julia.GAP.getindex( x )
, a value v
of the right type can be set with Julia.GAP.setindex( x, v )
, and one can check with Julia.GAP.isassigned( x )
whether x
has a value.
‣ Julia | ( global variable ) |
This global variable represents the Julia module Main
, see IsJuliaModule
(???).
The variables from the underlying Julia session can be accessed via Julia
, as follows.
gap> Julia.sqrt; # a Julia function <Julia: sqrt> gap> JuliaEvalString( "x = 1" ); # an assignment in the Julia session 1 gap> Julia.x; # access to the value that was just assigned 1 gap> Julia.Main.x; 1
Note that not all Julia variables are directly visible in its Main
module. For example, Julia variables from the interface to GAP are defined in the Julia module GAP
or its submodules. It is safe to access this module as Julia.GAP
.
gap> Julia.GAP; <Julia module GAP> gap> Julia.GAP.prompt; <Julia: prompt>
‣ JuliaTypeInfo ( juliaobj ) | ( function ) |
Returns: a string.
Returns the string that describes the Julia type of the object juliaobj.
gap> JuliaTypeInfo( Julia.GAP ); "Module" gap> JuliaTypeInfo( Julia.sqrt(2) ); "Float64" gap> JuliaTypeInfo( 1 ); "Int64"
‣ CallJuliaFunctionWithCatch ( juliafunc, arguments[, kwargs] ) | ( function ) |
Returns: a record.
The function calls the Julia function juliafunc with ordinary arguments in the GAP list arguments and optionally with keyword arguments given by the component names (keys) and values of the GAP record kwargs, and returns a record with the components ok
and value
. If no error occurred then ok
has the value true
, and value
is the value returned by juliafunc. If an error occurred then ok
has the value false
, and value
is the error message as a GAP string.
gap> fun:= Julia.sqrt;; gap> CallJuliaFunctionWithCatch( fun, [ 2 ] ); rec( ok := true, value := <Julia: 1.4142135623730951> ) gap> res:= CallJuliaFunctionWithCatch( fun, [ -1 ] );; gap> res.ok; false gap> res.value{ [ 1 .. Position( res.value, '(' )-1 ] }; "DomainError" gap> inv:= Julia.inv;; gap> m:= GAPToJulia( JuliaEvalString( "Matrix{Int}" ), [[1,2],[2,4]] ); <Julia: [1 2; 2 4]> gap> res:= CallJuliaFunctionWithCatch( inv, [ m ] );; gap> res.ok; false gap> res.value{ [ 1 .. Position( res.value, '(' )-1 ] }; "LinearAlgebra.SingularException" gap> fun:= Julia.range;; gap> CallJuliaFunctionWithCatch( fun, [ 2, 10 ], rec( step:= 2 ) ); rec( ok := true, value := <Julia: 2:2:10> ) gap> res:= CallJuliaFunctionWithCatch( fun, [ 2, 10 ], > rec( step:= GAPToJulia( "a" ) ) );; gap> res.ok; false gap> res.value{ [ 1 .. Position( res.value, '(' )-1 ] }; "MethodError"
‣ CallJuliaFunctionWithKeywordArguments ( juliafunc, arguments, kwargs ) | ( function ) |
Returns: the result of the Julia function call.
The function calls the Julia function juliafunc with ordinary arguments in the GAP list arguments and keyword arguments given by the component names (keys) and values of the record kwargs, and returns the function value.
Note that the entries of arguments and the components of kwargs are not implicitly converted to Julia.
gap> CallJuliaFunctionWithKeywordArguments( Julia.Base.round, > [ GAPToJulia( Float( 1/3 ) ) ], rec( digits:= 5 ) ); <Julia: 0.33333> gap> CallJuliaFunctionWithKeywordArguments( > Julia.Base.range, [ 2 ], rec( length:= 5, step:= 2 ) ); <Julia: 2:2:10> gap> m:= GAPToJulia( JuliaEvalString( "Matrix{Int}" ), > [ [ 1, 2 ], [ 3, 4 ] ] ); <Julia: [1 2; 3 4]> gap> CallJuliaFunctionWithKeywordArguments( > Julia.Base.reverse, [ m ], rec( dims:= 1 ) ); <Julia: [3 4; 1 2]> gap> CallJuliaFunctionWithKeywordArguments( > Julia.Base.reverse, [ m ], rec( dims:= 2 ) ); <Julia: [2 1; 4 3]> gap> tuptyp:= JuliaEvalString( "Tuple{Int,Int}" );; gap> t1:= GAPToJulia( tuptyp, [ 2, 1 ] ); <Julia: (2, 1)> gap> t2:= GAPToJulia( tuptyp, [ 1, 3 ] ); <Julia: (1, 3)> gap> CallJuliaFunctionWithKeywordArguments( > Julia.Base.( "repeat" ), [ m ], > rec( inner:= t1, outer:= t2 ) ); <Julia: [1 2 1 2 1 2; 1 2 1 2 1 2; 3 4 3 4 3 4; 3 4 3 4 3 4]>
The simplest way to execute Julia code from GAP is to call JuliaEvalString
(2.2-1) with a string that contains the Julia code in question.
gap> JuliaEvalString( "sqrt( 2 )" ); <Julia: 1.4142135623730951>
However, it is usually more suitable to create GAP variables whose values are Julia objects, and to call Julia functions directly. The GAP function call syntax is used for that.
gap> jsqrt:= JuliaEvalString( "sqrt" ); <Julia: sqrt> gap> jsqrt( 2 ); <Julia: 1.4142135623730951>
In fact, there are slightly different kinds of function calls. A Julia function such as Julia.sqrt
is represented by a GAP function object, and calls to it are executed on the C level, using Julia's jl_call
.
gap> fun:= Julia.sqrt; <Julia: sqrt> gap> IsJuliaObject( fun ); false gap> IsFunction( fun ); true gap> fun( 2 ); <Julia: 1.4142135623730951>
Note that in Julia any object (not just functions) is potentially callable (in fact this is the same as in GAP), for example Julia types can be
gap> smalltype:= Julia.Int32; <Julia: Int32> gap> IsJuliaObject( smalltype ); true gap> IsFunction( smalltype ); false gap> val:= smalltype( 1 ); <Julia: 1> gap> JuliaTypeInfo( val ); "Int32" gap> JuliaTypeInfo( 1 ); "Int64"
For the following operations, methods are installed that require arguments in IsJuliaObject
(2.1-1) and delegate to the corresponding Julia functions.
CallFuncList
(Reference: CallFuncList), delegating to Julia's func(args...)
syntax; this yields the function call syntax in GAP, it is installed also for objects in IsJuliaWrapper
(2.1-2),
access to and assignment of entries of arrays, via \[\]
(Reference: \[\]), \[\]\:\=
(Reference: \[\]\:\=), MatElm
(Reference: MatElm), and SetMatElm
(Reference: MatElm), delegating to Julia.Base.getindex
and Julia.Base.setindex
,
access to and assignment of fields and properties, via \.
(Reference: \.) and \.\:\=
(Reference: \.\:\=), delegating to Julia.Base.getproperty
and Julia.Base.setproperty
,
the unary arithmetic operations AdditiveInverseOp
(Reference: AdditiveInverseOp), ZeroOp
(Reference: ZeroOp), and OneOp
(Reference: OneOp), delegating to Julia.Base.\-
, Julia.Base.zero
, and Julia.Base.one
,
the binary arithmetic operations \+
(Reference: +), \-
(Reference: -), \*
(Reference: *), \/
(Reference: /), LeftQuotient
(Reference: LeftQuotient), \^
(Reference: ^), \=
(Reference: \=), \<
(Reference: \<), delegating to Julia.Base.\+
, Julia.Base.\-
, Julia.Base.\*
, Julia.Base.\/
, Julia.Base.\\
, Julia.Base.\^
, Julia.Base.\=\=
, and Julia.Base.\<
; the same methods are installed also for the case that only one argument is in IsJuliaObject
(2.1-1), and the other argument is an immediate integer.
gap> m:= GAPToJulia( JuliaEvalString( "Matrix{Int}" ), > [ [ 1, 2 ], [ 3, 4 ] ] ); <Julia: [1 2; 3 4]> gap> m[1,2]; 2 gap> - m; <Julia: [-1 -2; -3 -4]> gap> m + m; <Julia: [2 4; 6 8]>
‣ GetJuliaScratchspace ( key ) | ( function ) |
Returns: a string
Returns the path of a Julia scratchspace associated to the given key. This scratchspace gets created if it did not exist already, one can rely on the fact that the returned path describes a writable directory. Subsequent calls with the same key yield the same result, and calls with different keys yield different results. The directory may be removed by Julia as soon as the Julia package GAP.jl
gets uninstalled.
In a Julia session, one can ask for help about the object with the name obj
(a function or a type) by entering ?obj
, and Julia prints all matches to the screen. One can get the same output in a GAP session by entering ?Julia:obj
, cf. Section Reference: Invoking the Help in the GAP Reference Manual. For example, ?Julia:sqrt
shows the Julia help about the Julia function sqrt
(which is available in GAP as Julia.sqrt
).
Note that this way to access the Julia help is different from the usual access to GAP help books, in the following sense.
The qualifying prefix Julia:
is mandatory. Thus the help request ?sqrt
will show matches from usual GAP help books (there is one match in the GAP Reference Manual), but not the help about the Julia function sqrt
.
Since the prefix Julia:
does not belong to a preprocessed
help book with chapters, sections, index, etc., help requests of the kinds ?<
, ?<<
, ?>
, ?>>
are not meaningful when the previous help request had the prefix ?Julia:
. (Also requests with the prefix ??Julia:
do not work, but this holds also for usual GAP help books.)
The Julia help system is case sensitive. Thus ?Julia:sqrt
yields a match but ?Julia:Sqrt
does not, and ?Julia:Set
yields a match but ?Julia:set
does not.
The Julia help system does currently not support menus in case of multiple matches, all matches are shown at once, and this happens also in a GAP session.
No PDF or HTML version of the Julia help is supported in GAP, only the text format can be shown on the screen. Thus it does not make sense to change the help viewer, cf. Section Reference: Changing the Help Viewer in the GAP Reference Manual.
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, ?Julia:GAP.wrap_rng
yields the description of the Julia function wrap_rng
that is defined in the Julia module GAP
, whereas no match is found for the input ?Julia:wrap_rng
.
generated by GAPDoc2HTML