Reputation: 51
I have been puzzled by how to define and use custom module
in Julia.
For example, I defined a module
named myMoldule
to wrap a mutable struct Param
and a function add
in D:\\run\\defineModule.jl
:
module myMoldule
export Param, add
mutable struct Param
x ::Int64
y ::Int64
end
function add(x::Int64, y::Int64)
sum ::Int64
sum = x + y
return sum
end
end
and used this module in D:\\run\\useModule.jl
like:
include("D:\\run\\defineModule.jl")
using .myMoldule
function testModule()
param = Param(1, 2)
sum = add(param.x, param.y)
println(sum)
end
An error occurred when running testModule()
as follows:
julia> testModule()
ERROR: UndefVarError: Param not defined
Stacktrace:
[1] testModule() at D:\run\useModule.jl:8
[2] top-level scope at none:1
Note that I used the absolute path in the include(...)
to avoid using LOAD_PATH
stuff, and added .
before the module name (i.e., using .myMoldule
).
What seems to be the problem?
P.S.: Julia version information:
julia> versioninfo()
Julia Version 1.5.2
Commit 539f3ce943 (2020-09-23 23:17 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-9.0.1 (ORCJIT, skylake)
Environment:
JULIA_DEPOT_PATH = C:\Users\f\.julia;C:\opt\JuliaPro-1.5.2-1\Julia-1.5.2\local\share\julia;C:\opt\JuliaPro-1.5.2-1\Julia-1.5.2\share\julia
JULIA_LOAD_PATH = @;@v#.#;@stdlib
JULIA_NUM_THREADS = 6
JULIA_PKG_SERVER = pkg.juliahub.com
Upvotes: 5
Views: 1942
Reputation: 51
Questioner's note: The following new question voted downwards (perhaps) was extended form the original one and was well answered by Vitaliy Yakovchuk.
I fixed all the issues pointed out by Przemyslaw Szufel. In my case above, it's not the improper ways of naming that cause the issue.
Now, I have a better exmaple to clarify my issue.
Suppose that, to meet the needs, I have to seperate my julia source code into two modules, e.g., define of a mutable struct Param
in defineModule1.jl
and define of functions in defineModule2.jl
. The code scripts are as follows:
"D:\\run\\defineModule1.jl"
:module MyModule1
export Param
mutable struct Param
x::Int64
y::Int64
end
end # end of module
"D:\\run\\defineModule2.jl"
:include("D:\\run\\defineModule1.jl"); using .MyModule1
module MyModule2
export myAdd, mySubtract
function myAdd(param::Param)
return param.x + param.y
end
function mySubtract(param::Param)
return param.x - param.y
end
end # end of module
Note that Param
is not defined here, and to make Param
available, a line include("D:\\run\\defineModule1.jl"); using .MyModule1
is added as the first line of this file.
"D:\\run\\useModule.jl"
:include("D:\\run\\defineModule1.jl"); using .MyModule1
include("D:\\run\\defineModule2.jl"); using .MyModule2
function testModule()
param = Param(1, 2)
# call myAdd to get the sum of param.x and param.y
sumValue = myAdd(param)
println(sumValue)
# call mySubtract to get the difference of param.x and param.y
difValue = mySubtract(param)
println(difValue)
end
Note that both function myAdd(param)
and mySubtract(param)
in the script defineModule2.jl
need the predefined mutable struct Param
in defineModule1.jl
.
This is what I got when I run D:\\run\\useModule.jl
:
julia> include("D:\\run\\useModule.jl")
WARNING: replacing module MyModule1.
WARNING: replacing module MyModule1.
WARNING: replacing module MyModule2.
ERROR: LoadError: LoadError: UndefVarError: Param not defined
Stacktrace:
[1] top-level scope at D:\run\defineModule2.jl:7
[2] include(::String) at .\client.jl:457
[3] top-level scope at D:\run\useModule.jl:2
[4] include(::String) at .\client.jl:457
[5] top-level scope at none:1
in expression starting at D:\run\defineModule2.jl:7
in expression starting at D:\run\useModule.jl:2
I believed that, by using the following lines in the beginning of "D:\run\useModule.jl", the mutable struct Param
should have be found:
include("D:\\run\\defineModule1.jl"); using .MyModule1
include("D:\\run\\defineModule2.jl"); using .MyModule2
...
Still, error LoadError: UndefVarError: Param not defined
is reported.
So, Why can't Param
be found by D:\\run\\useModule.jl
?
Upvotes: 2
Reputation: 493
The issue happens because you are using .MyModule1
, not in the MyModule2
, and thus you import Param
to the Main module but not to the MyModule2
, thus Module2 does not see Param
.
If you will put using ..MyModule1
(two dots instead of one as you there is one more level) into MyModule2
this issue will go.
However, your code still will not work, since julia's include
function just runs all the content of the included file, thus even you included the same file, you will create different instances of the modules. This warning WARNING: replacing module...
indicates that somewhere in your code you might use the different version of the module (in you case, Main.Module1 and Main.Module2.Module1).
The common practice in julia is to include all the files in one place (they should be included only once). For instance, you can put all the includes in the file useModule.jl
:
include("./defineModule1.jl")
include("./defineModule2.jl")
using .MyModule1
using .MyModule2
function testModule()
param = Param(1, 2)
# call myAdd to get the sum of param.x and param.y
sumValue = myAdd(param)
println(sumValue)
# call mySubtract to get the difference of param.x and param.y
difValue = mySubtract(param)
println(difValue)
end
Do not include files in other places. e.g.
defineModule2.jl
content:
module MyModule2
using ..MyModule1
export myAdd, mySubtract
function myAdd(param::Param)
return param.x + param.y
end
function mySubtract(param::Param)
return param.x - param.y
end
end # end of module
Upvotes: 3
Reputation: 42244
Corrections to be made:
sum
is a function in Base
you should use a different namesum
variable (and it should be named something like mysum
)::
Once corrected your code works.
Upvotes: 3