# \[ANN\] PatModules.jl: a better module system for Julia

**URL:** <https://discourse.julialang.org/t/ann-patmodules-jl-a-better-module-system-for-julia/52226>\
**Category:** Package Announcements\
**Tags:** code-organization\
**Created:** [December 22, 2020, 1:09pm UTC](https://discourse.julialang.org/t/ann-patmodules-jl-a-better-module-system-for-julia/52226 "2020-12-22T13:09:19Z")\
**Posts on this page:** 1\
**Showing post:** 58

<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:** [December 26, 2020, 10:26pm UTC](https://discourse.julialang.org/t/ann-patmodules-jl-a-better-module-system-for-julia/52226/58 "2020-12-26T22:26:58Z")

</div>

> [@patrick-kidger](#):
>
> I spent a fair bit of time searching around looking at existing solutions to this problem, and existing thoughts on how things may be improved:
> 
> [Current recommended best practice 1](https://stackoverflow.com/a/63084743)  
> [Current recommended best practice 2](https://www.reddit.com/r/Julia/comments/hwxpgm/beginner_question_files_modules_and_include_vs/fz2lzwe/)  
> [Current way of performing relative imports](https://discourse.julialang.org/t/julia-relative-imports-issue-4600-exactly-how-not-that-difficult-is-it/34503/4)  
> [An example of what is done in existing major packages](https://github.com/SciML/OrdinaryDiffEq.jl/blob/f602235e46fa8c5880f65b677178e901595637e3/src/OrdinaryDiffEq.jl)  
> [A comparison to C++ (a language with the same basic issue)](https://github.com/JuliaLang/julia/issues/29966)  
> [#4600: a potential change, but not really a fix](https://github.com/JuliaLang/julia/issues/4600#issuecomment-327573232)
> 
> With the general overview being that (a) the problem exists, (b) it has already been acknowledged, but © there are at present no good solutions.

I suggest looking at the following as well:  
 → [Dependencies of src files inside a package](https://discourse.julialang.org/t/dependencies-of-src-files-inside-a-package/43144)

I also creating a doc [PR](https://github.com/JuliaLang/julia/pull/37167) to address this issue (I don’t suggest reading the PR thread because it’s a bit hard to read).

Instead, I’ll insert the PR text directly here:

# Inline text from [PR](https://github.com/JuliaLang/julia/pull/37167)

### Julia ⇔ C/C++: Namespaces

- C/C++ `namespace`s correspond roughly to Julia `module`s.
- There are no private functions/variables/modules/… in Julia. Everthing is accessible  
through fully qualified paths (or relative paths, if desired).
- `using MyNamespace::myfun` (C++) corresponds roughly to `import MyModule: myfun` (Julia).
- `using namespace MyNamespace` (C++) corresponds roughly to `using MyModule` (Julia)
  - In Julia, only `export`ed symbols are made available to the calling module.
  - In C++, only elements found in the included (public) header files are made available.

- Caveat: `import`/`using` keywords (Julia) also _load_ modules (see below).
- Caveat: `import`/`using` (Julia) works only at the global scope level (`module`s)
  - In C++, `using namespace X` works within arbitrary scopes (ex: function scope).

### Julia ⇔ C/C++: Module loading

- When you think of a C/C++ “ **library** ”, you are likely looking for a Julia “ **package** ”.
  - Caveat: C/C++ libraries often house multiple “software modules” whereas Julia  
“packages” typically house one.
  - Reminder: Julia `module`s are global scopes (not necessarily “software modules”).

- **Instead of build/`make` scripts** , Julia uses “Project Environments” (sometimes called  
either “Project” or “Environment”).
  - Build scripts are only needed for more complex applications  
(like those needing to compile, or download C/C++ executables 🙂 ).
  - C/C++ code typically target more conventional applications, whereas Julia  
“Project Environments” provide a set of packages to experiment with particular problem  
spaces. Julia users typically use problem-specific “scripts” for this type of experimentation.
  - To develop a “conventional” application/project in Julia, you can initialize its root directory  
as a “Project Environment”, and house application-specific code/packages there.  
This provides good control over project dependencies, and future reproducibility.
  - Available packages are added to a “Project Environment” with the `pkg> add` tool  
(This does not **load** said package, however).
  - The list of available packages (direct dependencies) for a “Project Environment” are  
saved in its `Project.toml` file.
  - The _full_ dependency information for a “Project Environment” is auto-generated & saved  
in its `Manifest.toml` file.

- Packages (“software modules”) available to the “Project Environment” are loaded with  
`import` or `using`.
  - In C/C++, you `#include <moduleheader>` to get object/function delarations, and link in  
libraries when you build the executable.
  - In Julia, whatever is loaded is available to _all other_ loaded modules through its  
fully qualified path (no header file required).
  - Use `import SomePkg: SubModule.SubSubmodule` (Julia) to access package submodules.

- **Directory-based package repositories** (Julia) can be made available by adding repository  
paths to the `Base.LOAD_PATH` array.
  - Packages from directory-based repositories do not require the `pkg> add` tool prior to  
being loaded with `import` or `using`. They are simply available to the project.
  - Directory-based package repositories are the **quickest solution** to developping local  
libraries of “software modules”.

### Julia ⇔ C/C++: Assembling modules

- In C/C++, `.c`/`.cpp` files are compiled & added to a library with build/`make` scripts.
  - In Julia, `import [PkgName]`/`using [PkgName]` statements load `[PkgName].jl` located  
in a package’s `[PkgName]/src/` subdirectory.
  - In turn, `[PkgName].jl` typically loads associated source files with calls to  
`include "[someotherfile].jl"`.

- `include "./path/to/somefile.jl"` (Julia) is very similar to  
`#include "./path/to/somefile.jl"` (C/C++).
  - However `include "..."` (Julia) is not used to include header files (not required).
  - **Do not use** `include "..."` (Julia) to load code from other “software modules”  
(use `import`/`using` instead).
  - `include "path/to/some/module.jl"` (Julia) would instantiate multiple versions of the  
same code in different modules (creating _distinct_ types (etc.) with the _same_ names).
  - `include "somefile.jl"` is typically used to assemble multiple files _within the same  
Julia package_ (“software module”). It is therefore relatively straightforward to ensure  
file are `include`d only once (No `#ifdef` confusion).

### Julia ⇔ C/C++: Module interface

- C++ exposes interfaces using “public” `.h`/`.hpp` files whereas Julia `module`s `export`  
symbols that are intended for their users.
  - Often, Julia `module`s simply add functionality by generating new “methods” to existing  
functions (ex: `Base.push!`).
  - Developers of Julia packages therefore cannot rely on header files for interface  
documentation.
  - Interfaces for Julia packages are typically described using docstrings, README.md,  
static web pages, …

- Some developers choose not to `export` all symbols required to use their package/module.
  - Users might be expected to access these components by qualifying functions/structs/…  
with the package/module name (ex: `MyModule.run_this_task(...)`).

### Julia ⇔ C/C++: Quick reference

| Software Concept | Julia | C/C++ |
| --- | --- | --- |
| unnamed scope | `begin` … `end` | `{` … `}` |
| function scope | `function x()` … `end` | `int x() {` … `}` |
| global scope | `module MyMod` … `end` | `namespace MyNS {` … `}` |
| software module | A Julia “package” | `.h`/`.hpp` files  
+compiled `somelib.a` |
| assembling  
software modules | `SomePkg.jl`: …  
`import subfile1.jl`  
`import subfile2.jl`  
… | `$(AR) *.o` ⇒ `somelib.a` |
| import  
software module | `import SomePkg` | `#include <somelib>`  
+link in `somelib.a` |
| module library | `LOAD_PATH[]`, \*Git repository,  
\*\*custom package registry | more `.h`/`.hpp` files  
+bigger compiled `somebiglib.a` |

\* The Julia package manager supports registering multiple packages from a single Git repository.  
  
\* This allows users to house a library of related packages in a single repository.  
  
\*\* Julia registries are primarily designed to provide versionning & distribution of packages.  
  
\*\* Custom package registries can be used to create a type of module library.

---

_[View the full topic](https://discourse.julialang.org/t/ann-patmodules-jl-a-better-module-system-for-julia/52226)._
