# \[ANN\] ThinModules.jl - lightweight module dependency resolver

**URL:** <https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256>\
**Category:** Package Announcements\
**Tags:** announcement\
**Created:** [July 25, 2021, 8:48am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256 "2021-07-25T08:48:35Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shuenhoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuenhoy/32/24058_2.png) [@Shuenhoy](https://discourse.julialang.org/u/Shuenhoy)\
**Post date:** [July 25, 2021, 8:48am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256/1 "2021-07-25T08:48:35Z")

</div>

Hello!

This is a small package [ThinModules.jl](https://github.com/Shuenhoy/ThinModules.jl), which tries to avoid the manual maintenance of module orders. Please look at the example:

```julia
using ThinModules 

@thinmod module MyModule
# all submodules inside can have free orders. 
# ThinModules would do the re-order.
    module B
        module B1
            import ...C.C2: x
            @show x
        end
        module B2
            y = 2
        end               
    end
    module C
        module C1
            import ...B.B2: y
            @show y
        end
        module C2
           x = 1
        end  
    end
end

```

Julia modules have to be written done in the right order when some depend on others. And `include` is just copy-and-paste, so when you have multiple files in your source tree, you also need to remember what’s the correct order of the `include`s, which could have been avoided easily and has already been avoided in almost every modern language.

There are already some attempts, e.g. [FromFile.jl](https://github.com/Roger-luo/FromFile.jl) by @Roger-luo and @patrick-kidger, which provides a Node.js-similar module management, where every file is a standalone implicit module and module dependency is just file dependency. That is very natural to me, and I love that a lot, but that seems not the favorite of many in the community. I guess probably because that is too different from the so far standard Julia codes.

So I made ThinModules.jl, which focuses on module-dependency resolving and tries to **keep things looking as similar to standard Julia as possible** , without an assumption of file-module mapping. When you use `include` without `module`, nothing happens. When you use `module` no matter they are in the same file or included from different files, they can be put in arbitrary order, and it works as long as there are no cyclic dependencies. Nothing else.

Look forward to your feedback!

_P.S. you would probably find it look like Rust’s module system, if you always use_ `module mymod; include("./mymod.jl"); end` _or_`module mymod; include("./mymod/mod.jl"); end` _and avoid bare_ `include`, _which is very like what Rust’s_ `mod mymod;` _does._

---

<div class="post-metadata">

**Author:** ![Skoffer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skoffer/32/378_2.png) [@Skoffer](https://discourse.julialang.org/u/Skoffer)\
**Post date:** [July 26, 2021, 8:10am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256/2 "2021-07-26T08:10:36Z")

</div>

Is it possible to do the same with `include`? I mean, in a situation, when we have

```julia
# file funcs.jl

function(x::A) = nothing

```

```julia
# file structs.jl

struct A end

```

to make a macro, which can pull structure definition to the top of the code, so

```julia
@multiinclude begin
  include("defs.jl")
  include("structs.jl")
end

```

generated a proper order of structures and functions?

---

<div class="post-metadata">

**Author:** ![Shuenhoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuenhoy/32/24058_2.png) [@Shuenhoy](https://discourse.julialang.org/u/Shuenhoy)\
**Post date:** [July 26, 2021, 8:41am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256/3 "2021-07-26T08:41:01Z")

</div>

Actually what you describe is not “do the same with `include`”, it is about the granularity of re-ordering and you want the single declarations within a block to be the granularity, while in ThinModules.jl the granularity of re-ordering is the module. `include` itself does not matter.

This could be possible, but it should be harder, with such flexibility than re-oreder modules. Taking module as the granularity, there is hard to be something wrong as long as the module top-level and ` __init__ ` don’t have codes with side-effects. But if we can re-order every declaration, I don’t know - there are too many possibilities. On the other hand, analyzing the dependency relationship between the declarations could also be harder than modules, where you mainly need to look at `using` and `import`.

I am not sure how hard is the above difficulties now, but it would indeed reduce more manual maintenance of codes order if it works.

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [July 26, 2021, 9:04am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256/4 "2021-07-26T09:04:57Z")

</div>

> [@Shuenhoy](#):
>
> it would indeed reduce more manual maintenance of codes order if it works.

I would note that when reading Julia code it is a recurring issue to find the location of referred types and functions. Auto-reordering by a preprocessor may make this even harder.

---

<div class="post-metadata">

**Author:** ![Shuenhoy](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/shuenhoy/32/24058_2.png) [@Shuenhoy](https://discourse.julialang.org/u/Shuenhoy)\
**Post date:** [July 26, 2021, 9:21am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256/5 "2021-07-26T09:21:27Z")

</div>

You are right. If no re-ordering, your searching space for a symbol in the same module is halved - you only need to look at the part before the reference. But, to really solve this problem, I think we have to rely on intelligence. And we may need a more suitable code structure, e.g. smaller modules. If every module does not cross files, such re-ordering should be fine.

This is also one reason why I made ThinModules.jl, I do prefer smaller modules, with explicit mutual dependences, and from `import X: y`, I can easily know where each symbol is from even when I don’t have LSP installed at hand. Though there would be some redundancy codes to write.

---

<div class="post-metadata">

**Author:** ![tisztamo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tisztamo/32/16200_2.png) [@tisztamo](https://discourse.julialang.org/u/tisztamo)\
**Post date:** [July 26, 2021, 10:00am UTC](https://discourse.julialang.org/t/ann-thinmodules-jl-lightweight-module-dependency-resolver/65256/6 "2021-07-26T10:00:54Z")

</div>

Yes, that kind of direct importing everything non-trivial is on my list of habits to build. That may also help the tools to find the correct locations. Language server fails to even start on some of my projects at the time, but I do not complain, static analysis of Julia is hard (if not impossible).

I really like the minimalism of ThinModules.jl, and I think its goal of looking standard-like may make it attractive for others too. Great work!
