Джулия @eval Мировой возраст несоответствие - PullRequest
1 голос
/ 23 мая 2019

Я пытаюсь использовать функцию julia @eval, чтобы загружать пакет PyPlot только по требованию.Однако я часто сталкиваюсь с несовпадением мировых возрастов.Вот минимальный пример, где я пытаюсь построить график по требованию

function CreateMatrix(Ncount;Plot=true)
    TheMatrix = fill(0.0,Ncount,Ncount)

    if Plot
        @eval using PyPlot
        ###"Plot the Matrix"
        PyPlot.figure()
        PyPlot.imshow(abs.(TheMatrix))
        PyPlot.colorbar()
    end
    return TheMatrix
end

CreateMatrix(10;Plot=false)
CreateMatrix(10;Plot=true)

С выводом

ERROR: LoadError: MethodError: no method matching figure()
The applicable method may be too new: running in world age 25063, while current world is 25079.
Closest candidates are:
  figure(!Matched::Any...; kws...) at ~/.julia/packages/PyPlot/fZuOQ/src/PyPlot.jl:148 (method too new to be called from this world context.)
Stacktrace:
 [1] #CreateMatrix#3(::Bool, ::Function, ::Int64) at myfile.jl:7
 [2] (::getfield(Main, Symbol("#kw##CreateMatrix")))(::NamedTuple{(:Plot,),Tuple{Bool}}, ::typeof(CreateMatrix), ::Int64) at ./none:0
 [3] top-level scope at none:0
 [4] include at ./boot.jl:317 [inlined]
 [5] include_relative(::Module, ::String) at ./loading.jl:1044
 [6] include(::Module, ::String) at ./sysimg.jl:29
 [7] exec_options(::Base.JLOptions) at ./client.jl:231
 [8] _start() at ./client.jl:425
in expression starting at myfile.jl:16

Кто-нибудь знает, как правильно использовать функциональность @eval?


РЕДАКТИРОВАТЬ

В одном из комментариев было предложено обернуть команду построения и добавить аннотацию @noinline, как показано ниже, но это не работает.

function CreateMatrix(Ncount;Plot=false)
    TheMatrix = fill(0.0,Ncount,Ncount)

    if Plot
        @eval using PyPlot
        ###"Plot the Matrix"
        ThePlotting(TheMatrix)
    end
    return TheMatrix
end

@noinline function ThePlotting(TheMatrix)
    PyPlot.figure()
    PyPlot.imshow(abs.(TheMatrix))
    PyPlot.colorbar()
end

CreateMatrix(10;Plot=false)
CreateMatrix(10;Plot=true)

Я использую julia версии 1.00,2

1 Ответ

1 голос
/ 23 мая 2019

Вы можете реализовать это так:

function CreateMatrix(Ncount;Plot=true)
    TheMatrix = fill(0.0,Ncount,Ncount)

    if Plot
        if isdefined(Main, :PyPlot)
            println("PyPlot already loaded")
            PyPlot.figure()
            PyPlot.imshow(abs.(TheMatrix))
            PyPlot.colorbar()
        else
            println("PyPlot loading PyPlot")
            @eval using PyPlot
            Base.invokelatest(PyPlot.figure)
            Base.invokelatest(PyPlot.imshow, abs.(TheMatrix))
            Base.invokelatest(PyPlot.colorbar)
        end
    end
    return TheMatrix
end

Я использовал условное выражение, чтобы вы могли видеть, какая ветвь выполняется при повторном вызове функции.

Изначально я думал, что при вызове не встроенной функции Юлия разрешает изменение возраста мира (но оказывается, что оно строгое).

Наконец, в целом, вероятно, безопаснее не писать такой код, а просто загрузить модуль в область видимости верхнего уровня (возможно, условно).

...