# Organisation into submodules and multiple dispatch

**URL:** <https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641>\
**Category:** General Usage\
**Tags:** module, dispatch\
**Created:** [June 3, 2020, 2:30am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641 "2020-06-03T02:30:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![sparrowhawk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sparrowhawk/32/9148_2.png) [@sparrowhawk](https://discourse.julialang.org/u/sparrowhawk)\
**Post date:** [June 3, 2020, 2:30am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/1 "2020-06-03T02:30:49Z")

</div>

I want to have a supermodule that contains a function, which carries out different operations depending on the input type. Depending on the type, this function is defined in various submodules. The submodules can be super complicated and standalone but here’s an MWE. Everything is in the `LOAD_PATH`

This is the supermodule

```julia
module SuperModule
include("SubModule1.jl")
include("SubModule2.jl")
end

```

These are the submodules in their `.jl` files in the `LOAD_PATH`

```julia
module SubModule1
    export foo
    foo(x::Int) = println("Hello there Int")
end

```

and

```julia
module SubModule2
    export foo
    foo(x::Float64) = println("Hello there Float")
end

```

now when I do a `using SuperModule` I get `[Info: Precompiling SuperModule [top-level]` as expected

However, doing ` SuperModule.foo(1.0)` or ` SuperModule.foo(1)` gives an `UndefVarError`

But of course, ` SuperModule.SubModule1.foo(1)` and `SuperModule.SubModule2.foo(1.0)` produce  
`Hello there Int` and `Hello there Float`

I can get the desired behaviour of `SuperModule.foo(x)` using `include`, without the `module` and `export` in the submodule files. But how do I get it to work using submodules? I will not be maintaining the packages in the submodules and an include without modules will not work for me in the long run.

Thanks

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [June 3, 2020, 2:43am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/2 "2020-06-03T02:43:50Z")

</div>

You need to add `using .SubModule1, .SubModule2` somewhere in `SuperModule`. It is through `using` that `export`ed names get imported into the current scope.

Example:

```julia
julia> module SuperModule

       module SubModule
           export foo
           foo() = println("This is SubModule.foo()")
       end

       using .SubModule

       end
Main.SuperModule

julia> SuperModule.foo()
This is SubModule.foo()

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [June 3, 2020, 2:45am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/3 "2020-06-03T02:45:40Z")

</div>

Currently both submodules define _separate_ functions that happen to share the name `foo`. Multiple dispatch isn’t working because those two `foo()` functions have nothing to do with one another, so there’s nothing for dispatch to do.

Fortunately, this is easy to fix. You need to define the function itself in the supermodule (you don’t need to give it any behavior, just declare that it exists), and then you need to explicitly extend that function in each submodule:

```julia
julia> module SuperModule
         # Define `foo()` but don't give it any methods yet
         function foo end
         
         # You can put this into SubModule.jl and do 
         # include("SubModule.jl") here, but I'm including 
         # it inline for this simple example.
         module SubModule1
           
          # Explicitly indicate that this is the *same* foo as in SuperModule
          import ..foo
           
          foo(x::Int) = println("hello Int")
        end
        
        module SubModule2
          import ..foo
          
          foo(x::Float64) = println("hello Float64")
        end
       end
Main.SuperModule

julia> SuperModule.foo(1)
hello Int

julia> SuperModule.foo(1.0)
hello Float64

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [June 3, 2020, 2:47am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/4 "2020-06-03T02:47:12Z")

</div>

> [@ettersi](#):
>
> You need to add `using .SubModule1, .SubModule2` somewhere in `SuperModule` .

This actually won’t help in the example provided above. Adding `using .Submodule1, .SubModule2` will make `foo` unusable because both submodules export _different_ functions with the name `foo`. You need the `import` command inside each submodule so that both submodules will extend the _same_ function rather than defining separate ones.

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [June 3, 2020, 2:49am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/5 "2020-06-03T02:49:06Z")

</div>

Right, I thought the question was merely about exporting the names and missed the part about adding methods to a shared function.

---

<div class="post-metadata">

**Author:** ![sparrowhawk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sparrowhawk/32/9148_2.png) [@sparrowhawk](https://discourse.julialang.org/u/sparrowhawk)\
**Post date:** [June 3, 2020, 5:04am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/6 "2020-06-03T05:04:23Z")

</div>

Beautiful, that’s quite clean! Since all the submodule packages will need to provide foo, and will be independently maintained, here’s how I followed your idea one step further such that each submodule can be maintained independently of the other ones (except one module file common to all defining an abstract `foo`).

```julia
module SuperModule
import AbstractModule.foo # is in LOAD_PATH

# could also be through an include
module SubModule1
    import AbstractModule.foo # is in LOAD_PATH
    foo(x::Int) = println("Hello there Int")
end

# could also be through an include
module SubModule2
    import AbstractModule.foo # is in LOAD_PATH
    foo(x::Float64) = println("Hello there Float")
end

end

```

and `AbstractModule.jl` is defined as

```julia
module AbstractModule
    function foo end
end

```

This works nicely in the REPL

```julia
any(pwd() .== LOAD_PATH) || push!(LOAD_PATH, pwd())
using Revise, SuperModule

julia> SuperModule.foo(1)
Hello there Int

julia> SuperModule.foo(1.0)
Hello there Float

```

But a nagging silly question here - how did `SuperModule` know about `foo` in any of the submodules? It wasn’t exported explicitly!

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [June 3, 2020, 6:12am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/7 "2020-06-03T06:12:06Z")

</div>

Your question is more easily answered if you rewrite

```julia
import AbstractModule.foo 
foo(x::Int) = println("Hello there Int")

```

as

```julia
AbstractModule.foo(x::Int) = println("Hello there Int")

```

The second version points out more clearly that `AbstractModule.foo(x::Int) = ...` adds a _method_ to the _function_ `AbstractModule.foo`. That is, you do not need to export `SuperModule.SubModuleX.foo()` because these identifiers are simply aliases for `AbstractModule.foo()`.

---

<div class="post-metadata">

**Author:** ![sparrowhawk](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sparrowhawk/32/9148_2.png) [@sparrowhawk](https://discourse.julialang.org/u/sparrowhawk)\
**Post date:** [June 3, 2020, 6:15am UTC](https://discourse.julialang.org/t/organisation-into-submodules-and-multiple-dispatch/40641/8 "2020-06-03T06:15:29Z")

</div>

Ah, ok thanks. I’ve liked your response.
