Мне было интересно, можно ли определить модули (или скрипты)
# SomeName.jl
module SomeName
export worker()
function worker()
println( @__FILE__ )
...
return
end
и
# SomeOtherName.jl
module SomeOtherName
export worker()
function worker()
println( @__FILE__ )
...
return
end
чтобы загружать их динамически и вызывать их стандартные рабочие функции, такие как
function foo()
...
modname = "SomeName" # in practice we would call something like retrievename()
mod = import( modname ) # imports the module (or includes the script)
mod.worker() # calls the worker function
end
Функциональность должна быть аналогична динамической загрузке с помощью Libdl.dlopen(), Libdl.dlsym() в LINUX или LoadLibrary(), GetProcAddress() в Windows. Но я предполагаю, что для Джулии это может быть даже более элегантно.
Было бы интересно узнать это как для модулей, так и для скриптов.
Вы можете сделать это, но это плохая идея, учитывая, как Джулия сочетает компиляцию с множественной отправкой.
Предположим, у вас есть следующий файл:
shell> more Foo3.jl
module Foo3
export hello
hello() = "hello3"
end
Теперь у вас может быть следующая функция:
function foo(m::AbstractString)
include(m * ".jl")
Main.eval(Meta.parse("using Main.$m"))
mod = getfield(Main, Symbol(m))
Base.invokelatest(mod.hello)
end
Обратите внимание, что в этом случае невозможно просто скомпилировать функцию foo
, поэтому нам пришлось использовать Base.invokelatest
.
Теперь вы можете протестировать его:
julia> foo("Foo3")
"hello3"
Обычно я загружаю все модули (имея их в виде пакетов Julia), а затем выбираю динамически, как в примере ниже:
julia> getfield(Main, Symbol("Foo3")).hello()
"hello3"
Вы просто удаляете строку include
. Остальной код посвящен модулям.
Хорошо, спасибо, работает отлично. Как это будет выглядеть для динамически загружаемых модулей вместо скриптов? (для небольших скриптов это имеет смысл, если кто-то хочет заменить вычислительную процедуру без остановки серверного процесса)