I have a module Mod1
stored in a file Mod1.jl
and a module Mod2
stored in a file Mod2.jl
. ‘Mod1’ exports a function userfun
that uses a function foo
which is defined in Mod2
. Mod2
also defines some new types.
module Mod1
export userfun
include("Mod2.jl")
using .Mod2
function userfun()
foo()
end
end
module Mod2
export foo
using InteractiveUtils # for subtypes function
abstract type MyAbstract end
struct MyStruct <: MyAbstract end
function foo()
subtypes(MyAbstract)
end
end
If I now write in a fresh REPL
include("Mod1.jl")
using .Mod1
userfun()
I get
1-element Vector{Any}:
Main.Mod1.Mod2.MyStruct
as expected. But if I now (say, a user accidentaly) repeat the inclusion of the module and call userfun
include("Mod1.jl")
userfun()
I get
Any[]
Seemingly MyAbstract
suddenly has now subtypes. If I afterwards redo using .Mod1
I get the same empty array.
Can anyone explain why the behavior changes after I include
the module twice (This is of course not the actual code, I have tried to distill the problem as much as possible)?
Thank you for the response. Poitn 2. does seem to aggree with the behavior.
Is 1. a general concept: One should not use modules unless it is wrapped into a package? Does a package always ensure that the module is not evaluated twice
?
To be clear, the problem isn’t loading the module twice (i.e. running using .Mod1
twice, which would be fine) but including the file twice, which messes up the modules, don’t do it.
1 Like
To elaborate:
julia> include("Mod1.jl")
Main.Mod1
julia> using .Mod1
julia> userfun()
1-element Vector{Any}:
Main.Mod1.Mod2.MyStruct
julia> using .Mod1
julia> userfun()
1-element Vector{Any}:
Main.Mod1.Mod2.MyStruct
as you can see, just doing using .Mod1
twice has no effect. When you include
the file the second time you missed a warning:
julia> include("Mod1.jl")
WARNING: replacing module Mod1.
Main.Mod1
julia> userfun()
Any[]
My guess is that Main.userfun
is the old Mod1.userfun
, which doesn’t see the old Mod1
anymore as it has been overwritten, but you should be able to call Mod1.userfun
and in fact
julia> Mod1.userfun()
1-element Vector{Any}:
Main.Mod1.Mod2.MyStruct
julia> userfun === Mod1.userfun
false
The summary is don’t include files twice, actually read the warnings, and only reload modules.
If you’re doing all of this in the REPL for quick development, you may want to look at Revise.jl
instead.