Freewill
Freewill

Reputation: 51

Error occurred when loading a custom Julia module

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

Answers (3)

Freewill
Freewill

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:

  1. "D:\\run\\defineModule1.jl":
module MyModule1

    export Param

    mutable struct Param
        x::Int64
        y::Int64
    end

end # end of module
  1. "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.

  1. "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

Vitaliy Yakovchuk
Vitaliy Yakovchuk

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

Przemyslaw Szufel
Przemyslaw Szufel

Reputation: 42244

Corrections to be made:

  • sum is a function in Base you should use a different name
  • no need to declare sum variable (and it should be named something like mysum)
  • Remove space before ::
  • Module names should start with a CapitalLetter
  • You have a typo in module name perhaps you are loading a different module than you think?

Once corrected your code works.

Upvotes: 3

Related Questions