R package JuliaCall does not work with Julia v1.9.1

Hello,

In order to use the R package JuliaCall, one firstly had to run the command julia_setup() in R. This command executes some Julia scripts. But it does not work. We get this error:

julia> ENV["R_HOME"] = "C:/Users/sdl96354/AppData/Local/Programs/R/R-4.3.1"
"C:/Users/sdl96354/AppData/Local/Programs/R/R-4.3.1"

julia> Base.include(Main,"C:/Users/sdl96354/AppData/Local/Programs/R/R-4.3.1/library/JuliaCall/julia/setup.jl")
[ Info: Precompiling RCall [6f49c342-dc21-5d91-9882-a32aef131414]
ERROR: LoadError: syntax: Global method definition around C:\Users\sdl96354\AppData\Local\Programs\R\R-4.3.1\library\JuliaCall\julia\JuliaObject.jl:77 needs to be placed at the top level, or use "eval".
Stacktrace:
 [1] top-level scope
   @ C:\Users\sdl96354\AppData\Local\Programs\R\R-4.3.1\library\JuliaCall\julia\JuliaObject.jl:75
 [2] include(mod::Module, _path::String)
   @ Base .\Base.jl:457
 [3] include(x::String)
   @ Main.JuliaCall C:\Users\sdl96354\AppData\Local\Programs\R\R-4.3.1\library\JuliaCall\julia\setup.jl:16
 [4] top-level scope
   @ C:\Users\sdl96354\AppData\Local\Programs\R\R-4.3.1\library\JuliaCall\julia\setup.jl:99
 [5] include(mod::Module, _path::String)
   @ Base .\Base.jl:457
 [6] top-level scope
   @ REPL[2]:1
in expression starting at C:\Users\sdl96354\AppData\Local\Programs\R\R-4.3.1\library\JuliaCall\julia\JuliaObject.jl:75
in expression starting at C:\Users\sdl96354\AppData\Local\Programs\R\R-4.3.1\library\JuliaCall\julia\setup.jl:16

Would you know what does that mean? Here is JuliaObject.jl:

import RCall.sexp

struct JuliaObject
    id :: Ptr{RCall.ExtPtrSxp}
    typ :: String
    JuliaObject(id :: Ptr{RCall.ExtPtrSxp}, typ = "Regular") = new(id, typ)
end

function getID(x :: JuliaObject)
    x.id
end

function getType(x :: JuliaObject)
    x.typ
end

function new_obj(obj, typ = "Regular")
    # wrap in a `Ref`
    refj = Ref(obj)
    jptr = pointer_from_objref(refj)
    s = RCall.makeExternalPtr(jptr)
    RCall.jtypExtPtrs[s] = refj
    RCall.registerCFinalizerEx(s)

    JuliaObject(s, typ)
end


## debugging for freeing
# function rm_obj(id)
#     RCall.decref_extptr(RCall.sexp(x))
# end

JuliaObject(x :: JuliaObject, typ = "Regular") = x
JuliaObject(x :: RObject, typ = "Regular") = new_obj(rcopy(x), typ)
JuliaObject(x :: RCall.Sxp, typ = "Regular") = new_obj(rcopy(x), typ)
JuliaObject(x, typ = "Regular") = new_obj(x, typ)

## Conversion related to JuliaObject

const makeJuliaObjectInR = reval("JuliaCall:::juliaobjectnew")

function sexp(x :: JuliaObject)
    RCall.rcall_p(makeJuliaObjectInR, getID(x), getType(x))
end

import RCall.rcopy

function rcopy(::Type{JuliaObject}, x::Ptr{EnvSxp})
    try
        # get(julia_object_stack, rcopy(Int32, RObject(x)[:getID]()))
        # get(julia_object_stack, rcopy(Int32, RObject(x)[:id]))
        RCall.jtypExtPtrs[RCall.sexp(x[:id])].x
    catch e
        nothing
    end
end

import RCall: RClass, rcopytype

rcopytype(::Type{RClass{:JuliaObject}}, x::Ptr{EnvSxp}) = JuliaObject

## Fallback conversions

@static if julia07
    import RCall.sexpclass
    sexpclass(x) = RClass{:JuliaObject}
    sexp(::Type{RClass{:JuliaObject}}, x) = sexp(JuliaObject(x))
else
    sexp(x) = sexp(JuliaObject(x))
end

## Regarding to issue #12, #13 and #16,
## we should use JuliaObject for general AbstractArray
@static if julia07
    @suppress_err begin
        JuliaCall.sexpclass(x :: AbstractArray{T}) where {T} = RClass{:JuliaObject}
    end

    ## AbstractArray{Any} should be converted to R List
    sexpclass(x :: AbstractArray{Any}) = RClass{:list}
else
    @suppress_err begin
        JuliaCall.sexp(x :: AbstractArray{T}) where {T} = sexp(JuliaObject(x))
    end

    ## AbstractArray{Any} should be converted to R List
    sexp(x :: AbstractArray{Any}) = sexp(VecSxp, x)
end

## Preserve BigFloat precision,
## as the design decision in issue #16
# sexp(x::AbstractArray{BigFloat}) = sexp(JuliaObject(x))
# sexp(x::BigFloat) = sexp(JuliaObject(x))

function setfield1!(object, name, value1)
    value = fieldtype(typeof(object), name)(value1)
    setfield!(object, name, value)
end

As you have seen on GitHub already, it appears JuliaCall is broken:

I use JuliaConnectoR usually but I tried it with v1.9.1 and it was incredibly slow. Is it broken too? Will take a look at the Github repo…

Or is it due to Windows? (my Linux laptop is broken). If somebody want to try that, the inversion of a 1000x1000 matrix, it is incredibly slow:

library(JuliaConnectoR)

juliaModule <- "
module myJuliaModule
export mySolveJulia
export myProdJulia

function mySolveJulia(m)
  return inv(m)
end

function myProdJulia(m1, m2)
  return m1 * m2
end

end
"

. <- juliaEval(juliaModule)
myJuliaModule <- juliaImport(".myJuliaModule", all = FALSE)
mySolveJulia <- myJuliaModule$mySolveJulia

mySolveR <- function(x) solve(x)
set.seed(9392927)
N <- 1e3L
x1 <- matrix(rpois(N^2L, lambda = 10), N)

reps <- 2L
microbenchmark::microbenchmark(
  mySolveR(x1), 
  mySolveJulia(x1),
  times = reps
)

stopJulia()