Reputation: 405
Let's say I have a module, Module1 defining a struct and a fit() function. I have another module, call it Parent, that includes Module1 and defines a test() function that also calls fit(). If I define the structure from Module 1 and then call test() from Parent I'm having trouble with the namespaces. Here's the code for this example:
#this module would be in a separate file
module Module1
struct StructMod1
end
export StructMod1
function fit(s::StructMod1)
end
export fit
end
module Parent
#including the module with include("Module1.jl")
module Module1
struct StructMod1
end
export StructMod1
function fit(s::StructMod1)
end
export fit
end
#including the exports from the module
using .Module1
function test(s::StructMod1)
fit(s)
return s
end
export test
end
using .Parent, .Module1
s = Parent.Module1.StructMod1()
@show test(s)
s2 = StructMod1()
@show test(s2)
And the output
test(s) = Main.Parent.Module1.StructMod1()
ERROR: LoadError: MethodError: no method matching test(::StructMod1)
Closest candidates are:
test(::Main.Parent.Module1.StructMod1)
Alternatively, if I replace using .Module1 with using ..Module1 then the definition of s2 works. But then, when calling using .Parent I have to make sure that Module1 is already loaded.
What is the best way to define a struct with one module and then use it with another module's functions?
Upvotes: 3
Views: 1370
Reputation: 6956
The double include is causing the error. In your example, Parent.Module1
is not the same as Module1
. Its useful to think of include
as a dumb copy/paste. Even though they share the same source file, the double include makes them appear as two different modules (as your example shows).
The solution is to include
only once and use relative imports to refer to the module.
As for organizing the whole set of modules, I like to include
all the modules sequentially in the main module and then use relative imports where needed. I find this to be the simplest approach.
The final version would look something like this:
# Module1.jl
module Module1
struct StructMod1
end
export StructMod1
function fit(s::StructMod1)
end
export fit
end
# Parent.jl
module Parent
using ..Module1
function test(s::StructMod1)
fit(s)
return s
end
export test
end
#Main.jl
include("Module1.jl")
include("Parent.jl")
using .Parent, .Module1
s = Parent.Module1.StructMod1()
@show test(s)
s2 = StructMod1()
@show test(s2)
Upvotes: 2