What is the correct way to import local modules in Pluto v0.18.0 notebooks with Julia 1.7.2?
The using
keyword adds exported members to the main namespace in Julia. Given a sample module, in foo.jl
,
module Foo
export bar
function bar()
return "baz"
end
end
The following code cell works in a Pluto Notebook:
# "baz"
begin
include("./foo.jl")
using .Foo
bar()
end
However, if I attempt to call bar
from another cell, I get the following error:
# UndefVarError: bar not defined
bar()
Though I notice that Foo.bar()
does work.
How do I add my own modules in a way that I get access to their exported members directly in the notebook's namespace?
This discussion gives a possible solution. It describes a better way of getting the module reference than what I have in my question.
If the module is not the last definition in the file, the import
function has to be redefined. A suggested name is to have a variant called "ingredients
"
#ingredients (generic function with 1 method)
function ingredients(path::String)
# this is from the Julia source code (evalfile in base/loading.jl)
# but with the modification that it returns the module instead of the last object
name = Symbol(basename(path))
m = Module(name)
Core.eval(m,
Expr(:toplevel,
:(eval(x) = $(Expr(:core, :eval))($name, x)),
:(include(x) = $(Expr(:top, :include))($name, x)),
:(include(mapexpr::Function, x) = $(Expr(:top, :include))(mapexpr, $name, x)),
:(include($path))))
m
end
Then the module can be loaded in like so (I don't know the reason why I have to say ingredients().Foo
)
#Main.Foo.jl.Foo
Foo = ingredients("My Library/Foo.jl").Foo
and then with the module reference, you have to manually bring all exported variables into the global scope:
#bar = bar (generic function with 1 method)
bar = Foo.bar