I had the same questions when I developed my own package.
The most important things to retain are:
- the logical structure of your program can be decoupled from the actual division in files (i.e. no reason to have necessarily one module == one file like in Python)
- you can have one top module and several submodules if you wish, although this is in general discouraged
- there is no issues in calling
import x
orusing x
several times in the code, BUTinclude("x.jl")
should be called only once.include
is like copying everything from the included file in the point where it has been included. - you can use the reexport package to automatically reexport the functions/objects you imported from an other module
In my case I have:
BetaMl.jl file:
module BetaML
include("Utils.jl")
using .Utils
include("Nn.jl")
using .Nn
include("Perceptron.jl")
using .Perceptron
include("Clustering.jl")
using .Clustering
end # module
Nn.jl file: (similar for the other files)
module Nn
using [list of packages I need for Nn functionality]
@reexport using ..Utils # note the two dots in front to go one level up, as these two modules are siblings
export [list of Nn module provided functions]
[...code...]
include("Nn_default_layers.jl")
[...code...]
include("Nn_default_optalgs.jl")
[...code...]
end # end module
In the “Nn_default_layers.jl” and “Nn_default_optalgs.jl” file I then have:
using [list of packages I need in this "section" of the Nn module ]
export [list of functions/objs provided in this "section" of the Nn module ]
[...code...]
An user of the package can then access its functionality either by using
the specific submodule of interest and then directly the provided functionality or by using
the root module BetaML
and then prefix with BetaML.
each object/function she/he want to use, e.g.:
using BetaML.Nn
myLayer = DenseLayer(2,3)
or, equivalently,
using BetaML
res = BetaML.kernelPerceptron([1.1 2.1; 5.3 4.2; 1.8 1.7], [-1,1,-1])