How best to use a custom module?

Hi guys,

I have been away from Julia since end of 2018. Now coming back and looking at my old code now with Julia 1.7, I feel puzzled at how best to use my own modules.

My modules are in subdirectories under the root directory of my project. Like:

./A/ModuleA.jl
./B/ModuleB.jl

ModuleB uses ModuleA. In my original code of B.jl, I have simply:
using ModuleA

Then at the REPL started at the root directory, I do:
include(“B/ModuleB.jl”)

It doesn’t work now as I learned that I need to set the LOAD_PATH. So I added both A and B onto the LOAD_PATH, then the above include statement works. But my problem is in VSCode, “goto definition” on a function defined in ModuleA doesn’t work.

Then ModuleB.jl I added:
include("…/A/ModuleA.jl")
just before
using ModuleA

Then “goto definition” works in VSCode. But in REPL,
include(“B/ModuleB.jl”)
gives my a warning like:
using A.ModuleA in module ModuleB conflicts with an existing identifier.

So what’s a proper solution to my problem?

Is it too difficult a question please?

The definitions clash because you are using them via the LOAD_PATH and the include.

Use one or the other

If I don’t list the subdirectories in LOAD_PATH and just have include("…/A/ModuleA.jl") in ModuleB.jl, then when I do include(“B/ModuleB.jl”) in root directory, I get error:
ERROR: LoadError: ArgumentError: Package ModuleA not found in current path

You either have to do

julia> push!(LOAD_PATH, "./A")
julia> push!(LOAD_PATH, "./B")
julia> using ModuleA
[ Info: Precompiling A [top-level]

julia> using ModuleB
[ Info: Precompiling B [top-level]

or

$ mkdir A/src && mv A/ModuleA.jl A/src/
$ mkdir B/src && mv B/ModuleB.jl B/src/ # had a typo (fixed)
$ julia -q

julia> push!(LOAD_PATH, ".")
julia> using ModuleA
[ Info: Precompiling ModuleA [top-level]
julia> using ModuleB
[ Info: Precompiling ModuleB [top-level]
1 Like

Is A/src/ supposed to be B/src/ ?

1 Like

oh, yes. copy pasting error

1 Like

I was actually using your first approach. It works at REPL, but my problem was in VSCode I can’t goto definition in ModuleB.jl. So I added include("…/A/ModuleA.jl") there and VSCode works, but then I got the warning of conflict identities.

I tried your second approach with a src subdirectory under each subdirectory of the modules. But it doesn’t seem to work at all. I am not sure how src comes to solve the problem.

With the jl files under its respective src subdirectory, now I start julia in root directory:

$ julia
_
_ _ ()_ | Documentation: https://docs.julialang.org
() | () () |
_ _ | | __ _ | Type “?” for help, “]?” for Pkg help.
| | | | | | |/ ` | |
| | |
| | | | (
| | | Version 1.7.2 (2022-02-06)
/ |_|||_’_| | Official https://julialang.org/ release
|__/ |

julia> push!(LOAD_PATH, “.”)
4-element Vector{String}:
“@”
@v#.#”
@stdlib
“.”

julia> using ModuleA
ERROR: ArgumentError: Package ModuleA not found in current path:

  • Run import Pkg; Pkg.add("ModuleA") to install the ModuleA package.

Stacktrace:
[1] require(into::Module, mod::Symbol)
@ Base ./loading.jl:967

OK, this time with includes and testing in VSCode

#==

matt@fort:~/discourse$ find . | sort

.
./A
./A/A.jl
./B
./B/B.jl
./main.jl


==#

include("A/A.jl")
include("B/B.jl")

using .A 
using .B 

1 Like

My issue is since B.jl uses A, in B.jl I need to have:

include("…/A/A.jl")
using A

The above satisfies VSCode for getting to the definition.

But then in REPL when I do:
using B

Julia complains about the conflicts. Like:
WARNING: using A.A in module B conflicts with an existing identifier

The use of multiple includes is what’s causing the problem.

You could try this where they are all in the same source file

Or add moduleA to the Manifest of moduleB using Pkg.add(path="/path/to/A"), create a project in a separate directory to include moduleA and moduleB as dependencies.

getting all my code into one course file is not an option.

Perhaps I will try to put my modules into a package.

I found the core of my issue relates to this unsolved thread:

Another option could be to split files and add a third module C that contains the code from A that uses B and the code from B that uses A. Then put

using A,B

into module C. To me this seems less fragile anyway.

I would strongly recommend this. Once you’ve got used to putting things into packages, it seems pretty natural, and in my experience VSCode copes with that as well.

Just tried to make my modules packages. Basically created one package for one module. It appears much simpler than I imagined.

But I am stuck with a module that has submodules. After the parent module is made a package, it demands about including the submodules as dependences. I know how to add local packages as dependencies with “Pkg> dev MyPackage”, but that doesn’t do for submodules. What can I do about the submodules?

It depends how you’re trying to access the other modules in your parent module. For submodules, you usually use include, followed by using:

module C
include("/path/to/submoduleA")
include("/path/to/submoduleB")
using .A
using .B
end

Note the dots before the module names.
If A and B are not submodules, but standalone packages, you need to do either

Pkg> dev /path/to/package

or

Pkg> add /path/to/package

The difference is that dev will track changes to the packages, add will take a snapshot of the current state and not track changes.
The choice between submodules or standalone modules depends on your use case.

That works. So I created my packages. Code runs, but I am still having trouble with VSCode not recognizing my own packages.

Say in package C, I have:

module C
using DataFrames
using MyPackageA
end

I have set both DataFrames and MyPackageA as dependencies of C. In VSCode, DataFrames is recognized but MyPackageA is not.

I build my packages with this procedure:

(v1.7) pkg> generate MyPackage

julia> cd("MyPackage")

pkg> activate .

(MyPackage) pkg> add DataFrames

(MyPackage) pkg> dev ../MyPackage1

What is wrong?

Although I use VSCode occasionally, I’m not very familiar with the details. If I understand this post correctly, you might need to run in an activated environment that includes your packages as dependencies. You might already be doing that, so you might need to ask another discourse question.

See my answer here: Best practise: organising code in Julia - #2 by stevengj

2 Likes

I very agree on this. My other side of the issue beyond code structuring is getting VSCode to function. There seems quite much lack there.