# Defining multiple modules in a package

**URL:** <https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702>\
**Category:** General Usage\
**Tags:** package\
**Created:** [January 1, 2021, 6:35pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702 "2021-01-01T18:35:11Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)\
**Post date:** [January 1, 2021, 6:35pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/1 "2021-01-01T18:35:11Z")

</div>

I am developing two packages. Let’s call them “A” and “B”. Package “A” defines several modules, let’s call them “d”, “e”, and “f”. I have activated environment B from Pkg and made package A a dependency.

A.jl:

```
module A
    include("d.jl")
    using .d: f
    export f

    include("e.jl")
    include("f.jl")
end

```

When I try to use functions defined in d.jl from code in package B:

```
module B
    import A
    import A.d

    A.d.f()
end

```

I very reliably get the error

```
ERROR: LoadError: UndefVarError: d not defined

```

I’ve tried every permutation of include’s, import’s, using’s, and dot notation I can think of. The error never changes.

EDIT:

This was user error. The problem was that there was already a package named “A” installed (which, needless to say, doesn’t define anything named “d”), and "using A’’ found that package instead of the one I was writing.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 1, 2021, 7:03pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/2 "2021-01-01T19:03:11Z")

</div>

This works, perhaps that gives you a direction:

```julia
julia> module A
         module A1
            f(x) = x + 1
         end
       end
Main.A

julia> module B
         import ..A.A1 # two dots
         g(x) = A1.f(x)
       end
Main.B

julia> B.g(1)
2

```

Ps. I don’t think that module names can start with numbers.

(otherwise I think that if `A` is a package already installed you should be able to use `using A` . I am not sure if what you are seeing results from including the files containing the modules).

---

<div class="post-metadata">

**Author:** ![GlenHenshaw](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/glenhenshaw/32/5269_2.png) [@GlenHenshaw](https://discourse.julialang.org/u/GlenHenshaw)\
**Post date:** [January 1, 2021, 7:10pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/3 "2021-01-01T19:10:46Z")

</div>

I’m not actually naming the modules starting with numbers. I’ve changed the question accordingly.

---

<div class="post-metadata">

**Author:** ![MA\_Laforge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ma_laforge/32/385_2.png) [@MA\_Laforge](https://discourse.julialang.org/u/MA_Laforge)\
**Post date:** [January 1, 2021, 8:09pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/4 "2021-01-01T20:09:33Z")

</div>

### Step 1: No need for using here

Ok, so first thing is: you don’t need to do `using .d:f`. That’s just if you wish to have the `f` “symbol” _ **directly** _ available from the `A` module.

Julia doesn’t do information hiding, so as long as your code is “sourced”/loaded, you can access the structures/functions (actually referred to as “symbols”) through their path. BTW: The thing that loads your code is “`include()`”.

So again, the first step is tor remove `using .d:f` - and, I suppose `export f` - unless you _ **actually want** _ `f` to be available _ **directly** _ from the `A` module:

> [@GlenHenshaw](#):
>
> ```julia-auto
> module A
> include("d.jl")
> using .d: f
> export f
> 
> include("e.jl")
> include("f.jl")
> end
> 
> ```

### Step 2: Lesson on `module`

Julia `module`-s are not really “software modules”. They are actually software _ **namespaces** _ - and `include()`-ing a file does not automatically create said namespace. So, if you want the modules you wrote down in your example, you’d have to do the following:

A.jl:

```julia-auto
module A
    module d
        include("d.jl")
    end #module d
    module e
        include("e.jl")
    end #module 3
    module f
        include("f.jl")
    end #module f
end

```

Then, you could do the following in package B:

```julia-auto
module B
    import A
    #import A.d #Again, no point in importing if you qualify with explicit paths

    #Qualifying f() call with explicit path to A.d.f()
    #... so only need to "import A" to get "A" symbol
    A.d.f()
end

```

---

<div class="post-metadata">

**Author:** ![MA\_Laforge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ma_laforge/32/385_2.png) [@MA\_Laforge](https://discourse.julialang.org/u/MA_Laforge)\
**Post date:** [January 1, 2021, 8:19pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/5 "2021-01-01T20:19:00Z")

</div>

### Step 3: no need for modules/namespaces

But my guess is that you never really wanted to create sub-modules d, e, & f.

Given that you were trying to do `using .d:f` from module A, my guess is that you really are just using separate files to break up your software into a more manageable solution:

Awesome; keep doing that 🙂 . It’s much easier to find code if you split up large solution into separate files.

But that means you can stick with a simpler structure:

A.jl

```julia-auto
module A
    include("d.jl")
    include("e.jl")
    include("f.jl")
end

```

Yup. That’s it. Now, all the code from d.jl, e.jl, and f.jl are now part of module A.

### very\_long\_function\_names\_to\_avoid\_name\_collisions

If you don’t need to split things into submodules - don’t. In julia, I find there is rarely a reason to do so.

In most languages, you need namespaces to avoid creating `very_long_function_names_to_avoid_name_collisions` - but that isn’t typically necessary in Julia.

### Leverage multiple dispatch

…instead of relying on namespaces.

If you want to create a method of `push!()` that behaves differently for your values, you simply create your own `struct MyType`, and define a special `Base.push!(::MyType, ...)` method - and it automatically plays nice with the rest of Julia. The same can be done with any other function.

---

<div class="post-metadata">

**Author:** ![MA\_Laforge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ma_laforge/32/385_2.png) [@MA\_Laforge](https://discourse.julialang.org/u/MA_Laforge)\
**Post date:** [January 1, 2021, 8:21pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/6 "2021-01-01T20:21:18Z")

</div>

You might also look at the example here:  
 → [Dependencies of src files inside a package](https://discourse.julialang.org/t/dependencies-of-src-files-inside-a-package/43144)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 1, 2021, 11:02pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/7 "2021-01-01T23:02:39Z")

</div>

I think I understand what he is saying:

1. Create two packages, `Package1` and `Package2` with `PkgTemplates`.

2. `Package1` contains:

```julia
module Package1
  module Package1_A
    f(x) = 2*x
  end
end

```

1. `Package2` contains:

```julia
module Package2
  using Package1
  g(x) = Package1.Package1_A.f(x)
  export g
end      

```

1. Go to to `dir/Package2`, and start Julia with `julia --project` such that an environment for `Package2` is created. Then, add `Package1` :

```julia
(Package2) pkg> add ../Package1
    Cloning git-repo `/home/leandro/Drive/Work/JuliaPlay/packages/Package1`
   Updating git-repo `/home/leandro/Drive/Work/JuliaPlay/packages/Package1`
   Updating registry at `~/.julia/registries/General`
  Resolving package versions...
Updating `~/Drive/Work/JuliaPlay/packages/Package2/Project.toml`
  [231e8d6a] + Package1 v0.1.0 `../Package1#master`
Updating `~/Drive/Work/JuliaPlay/packages/Package2/Manifest.toml`
  [231e8d6a] + Package1 v0.1.0 `../Package1#master`

julia> using Package2
[Info: Precompiling Package2 [422864b9-2805-4bb9-af4e-8ecfc857a12e]

```

1. Finally, Try to use the function `g`, which is defined in `Package2`:

```julia
julia> Package2.g(1)
ERROR: UndefVarError: Package1_A not defined
Stacktrace:
 [1] getproperty at ./Base.jl:26 [inlined]
 [2] g(::Int64) at /home/leandro/Drive/Work/JuliaPlay/packages/Package2/src/Package2.jl:5
 [3] top-level scope at REPL[4]:1

julia>

```

edit: It seems that the issue not related to the the nested modules. Simply the functions of `Package1` are not loaded, it is like if `Package1` was empty.

---

<div class="post-metadata">

**Author:** ![PetrKryslUCSD](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petrkryslucsd/32/215825_2.png) [@PetrKryslUCSD](https://discourse.julialang.org/u/PetrKryslUCSD)\
**Post date:** [January 1, 2021, 11:47pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/8 "2021-01-01T23:47:49Z")

</div>

What if one does

```julia
using Package1.Package1_A: f

```

? These types of references work for me.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 1, 2021, 11:56pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/9 "2021-01-01T23:56:22Z")

</div>

Actually what I have done turns out to hit in a simpler problem, which I do not know if it is the same as the OPs:

Given a single package, `Package1`, in directory `../Package1`. Currently the main module of this package contains:

```julia
module Package1
  f(x) = 2*x
end

```

And then, if I try to use it, I get:

```julia
(@v1.5) pkg> add ../Package1
   Updating git-repo `/home/leandro/Drive/Work/JuliaPlay/packages/Package1`
   Updating registry at `~/.julia/registries/General`
######################################################################## 100,0%
  Resolving package versions...
Updating `~/.julia/environments/v1.5/Project.toml`
  [231e8d6a] + Package1 v0.1.0 `../../../Drive/Work/JuliaPlay/packages/Package1#master`
Updating `~/.julia/environments/v1.5/Manifest.toml`
  [231e8d6a] + Package1 v0.1.0 `../../../Drive/Work/JuliaPlay/packages/Package1#master`

julia> using Package1

julia> Package1.f
ERROR: UndefVarError: f not defined
Stacktrace:
 [1] getproperty(::Module, ::Symbol) at ./Base.jl:26
 [2] top-level scope at REPL[3]:1

julia>

```

Curiously, using `dev` seems to be reading the latest version (I changed the version to 0.1.1), but still the result is the same:

```julia
(@v1.5) pkg> dev ../Package1
Path `../Package1` exists and looks like the correct package. Using existing path.
  Resolving package versions...
Updating `~/.julia/environments/v1.5/Project.toml`
  [231e8d6a] + Package1 v0.1.1 `../../../Drive/Work/JuliaPlay/packages/Package1`
Updating `~/.julia/environments/v1.5/Manifest.toml`
  [231e8d6a] + Package1 v0.1.1 `../../../Drive/Work/JuliaPlay/packages/Package1`

julia> using Package1

julia> Package1.f
ERROR: UndefVarError: f not defined
Stacktrace:
 [1] getproperty(::Module, ::Symbol) at ./Base.jl:26
 [2] top-level scope at REPL[9]:1

```

Thus, if this is the problem, it is actually to know how to install and load a package that is in a local folder.

---

<div class="post-metadata">

**Author:** ![MA\_Laforge](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ma_laforge/32/385_2.png) [@MA\_Laforge](https://discourse.julialang.org/u/MA_Laforge)\
**Post date:** [January 2, 2021, 2:14am UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/10 "2021-01-02T02:14:24Z")

</div>

> [@lmiq](#):
>
> Thus, if this is the problem, it is actually to know how to install and load a package that is in a local folder.

Yes @lmiq. It is also true that you have to build your package folders correctly, and use the package manager correctly. This is definitely another possible source of issues (took me a while to understand what Julia wants).

## Possible issues with your solution

### Relative paths

My first suggestion would be to avoid using relative paths at all when you `add` or `dev` a package. Since I’m pretty sure you don’t know what will be the “current directory” (I sure don’t), to me, that seems like a bad way to learn how to use the package manager correctly:

> [@lmiq](#):
>
> `(@v1.5) pkg> add ../Package1`

By looking carefully at the package manager output, it would appear that you are using a relative path:

> [@lmiq](#):
>
> ```julia-auto
> Resolving package versions...
> Updating `~/.julia/environments/v1.5/Project.toml`
> [231e8d6a] + Package1 v0.1.0 `../../../Drive/Work/JuliaPlay/packages/Package1#master`
> 
> ```

I’m pretty sure this is a problem waiting to happen unless you really know what you are doing.

### `add` vs `dev`

Indeed. `pkg> add` is not the best choice to to add packages under development. Each time you would want to test a change in your code, you’d have to:

1. `bash$ git commit .` (The changes to your package).
2. `pkg> up` (make Juila update which version of your package it uses).

Otherwise, you will be testing out old code.

### Going back to relative paths:

> [@lmiq](#):
>
> ```julia-auto
> (@v1.5) pkg> dev ../Package1
> Path `../Package1` exists and looks like the correct package. Using existing path.
> 
> ```

Look at the package manager output:

- It looks to me like you tried developing a package that was already registered by the package manager - so instead of pointing to your new directory, it kept using the old version of your package.

### Once added, you don’t specify paths anymore

Since you already had a `Package1`, the `dev` command should have just been:

```julia-auto
(@v1.5) pkg> dev Package1

```

That will correctly switch you over to `dev` mode on `Package1`.

If you wish to switch to a different “`Package1`”, then I suggest the following:

```julia-auto
(@v1.5) pkg> rm Package1
(@v1.5) pkg> dev /abs/path/to/new/Package1

```

### Works for me

I tried creating your `Package1`, just to make sure I am not misleading anyone:

> [@lmiq](#):
>
> ```julia-auto
> module Package1
> module Package1_A
> f(x) = 2*x
> end
> end
> 
> ```

But on my side, I stuffed this code in a package I “generate”-ed with the package manager:

```julia-auto
(v1.3) pkg> generate Package1

```

So, this code went into my new `./Package1/src/Package1.jl`. Everything worked fine:

```julia
(v1.3) pkg> dev /abs/path/to/new/Package1

julia> using Package1
julia> Package1.Package1_A.f(3)
6

```

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 2, 2021, 9:46am UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/11 "2021-01-02T09:46:21Z")

</div>

Thank you for the answer! What was making things not work here was that I was not commiting the changes (`git add -A; git commit -m "update message"`) in `Package1`.

The relative path seem to to work as well the the absolute path (not sure if that is safe, but it works, actually it would be good that it was, because no warning or anything is printed).

Concerning `add` or `dev`, both work in what concerns the path, but good point remembering that with `dev` there is no need to `update` the package.

Thus, concerning my previous posts: What I did wrong there is not commiting the changes when the packages were modified. Not sure if that was the same problem OP was facing, though.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 2, 2021, 11:47am UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/12 "2021-01-02T11:47:22Z")

</div>

Anyway, that makes me wonder, what is the most practical way to develop simultaneously two packages, one that depends on the other? Revise won’t track the changes of the dependencies.

I guess that is not such an unusual scenario, is it?

---

<div class="post-metadata">

**Author:** ![magister-ludi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/magister-ludi/32/4003_2.png) [@magister-ludi](https://discourse.julialang.org/u/magister-ludi)\
**Post date:** [January 2, 2021, 12:39pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/13 "2021-01-02T12:39:31Z")

</div>

I do this all the time. I `dev` the packages that I’m working on. Julia recognises changes and recompiles at startup, `Revise` tracks changes in a REPL session.

EDIT: I always use the full path. I can think of too many ways things could go wrong with relative paths.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 2, 2021, 12:50pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/14 "2021-01-02T12:50:12Z")

</div>

> [@magister-ludi](#):
>
> `Revise` tracks changes in a REPL session

Of a module that is loaded with `using` from inside the main module of another package? Certainly not in general, does it for some specific setup?

---

<div class="post-metadata">

**Author:** ![magister-ludi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/magister-ludi/32/4003_2.png) [@magister-ludi](https://discourse.julialang.org/u/magister-ludi)\
**Post date:** [January 2, 2021, 12:55pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/15 "2021-01-02T12:55:11Z")

</div>

I’m not at a computer right now, so I can’t confirm, but I think that if the package that is pulled in by `using` has been `dev`’d, then it works. I won’t be able to check until tomorrow. If nobody has given you the answer by then, I’ll let you know.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [January 2, 2021, 1:27pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/16 "2021-01-02T13:27:09Z")

</div>

Yes, it does work. Cool.

So the way to go is to `dev` all packages being developed and using `Revise`.

One possible source of confusion is that when one does `dev Package1` the source being tracked is that of the default development directory (usually `.julia/dev/`), even if the package was originally installed from another local directory. That behavior is natural if the package was installed from an online repository, but not so from a local version. Thus, we should be careful and use `dev /path/to/Package1`, otherwise two copies of the package will be available, causing confusion.

---

<div class="post-metadata">

**Author:** ![magister-ludi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/magister-ludi/32/4003_2.png) [@magister-ludi](https://discourse.julialang.org/u/magister-ludi)\
**Post date:** [January 2, 2021, 11:19pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/17 "2021-01-02T23:19:56Z")

</div>

> [@lmiq](#):
>
> we should be careful and use `dev /path/to/Package1`

Yes, I was going to mention that once I had done some experiments, but you got there first 👍 I’m pleased it’s working for you now.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [November 23, 2023, 8:52pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/18 "2023-11-23T20:52:44Z")

</div>

@magister-ludi and @lmiq: in VS Code, do you have the two packages you are developing open in two separate windows (_each with its own environment_)?

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [November 23, 2023, 10:49pm UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/19 "2023-11-23T22:49:26Z")

</div>

I don’t

---

<div class="post-metadata">

**Author:** ![magister-ludi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/magister-ludi/32/4003_2.png) [@magister-ludi](https://discourse.julialang.org/u/magister-ludi)\
**Post date:** [November 24, 2023, 12:45am UTC](https://discourse.julialang.org/t/defining-multiple-modules-in-a-package/52702/20 "2023-11-24T00:45:16Z")

</div>

I don’t use VSCode much, but I’m not really sure what you are trying to understand.

If package `A` is a package that is used by package `B` (using `dev`, not `add`), then it shouldn’t matter if files from package `A` are open in an editor window. Once the files are saved to disk, the package `B` environment should notice and ‘revise’ the package. The environment that package `A` is using, shouldn’t make a difference.
