Multiple submodules inside a main module, with each submodule in one file

990 views
Skip to first unread message

Adrian Salceanu

unread,
Dec 29, 2015, 11:00:02 AM12/29/15
to julia-users
Hi! 

I'm trying to figure out how to split a module across multiple files. Or better put, to have multiple submodules inside a main module, with each submodule in one file. However, I always end up with the latest file overwriting the module code previously imported (last submodule overwrites the previous submodule). 

Example: 

=============

# file: a.jl
module Test

module A

export a

function a()
  println("a")
end

end

end

==============

# file: b.jl

module Test

module B

export b

function b()
  println("b")
end

end

end

===============

Expected result: 
upon including both files in a 3rd file or REPL, Test.A.a() and Test.B.b() should both be in scope. 

Actual result: 
last included file overwrites everything in Test, so either Test.A.a() or Test.B.b() are in scope, but not both. 

================

Where am I going with this? 
I'm interested in applying a design pattern common in ruby (rails) or elixir. In these languages one can split a module (or class/type definition) across multiple files and with each inclusion, the module/class/type is reopened, and the new methods are appended. 

Why doing this? 
Coming from ruby/elixir, it's an excellent way of organizing a complex codebase. I'm coding a web framework and I want all the framework code to be in a Framework super-module - with submodules for each major feature, like Router, Server, Controller, etc. To encapsulate the framework code in a structure like Framework.Router, Framework.Server, etc. 
Then the user app, a instance implementation of the web framework would be in a module of it's own, say AppName, with it's own submodules for Routes, Config, etc. Resulting in AppName.Routes, AppName.Config, etc. (Similar to how rails organizes the apps). 

Is this possible? If yes, how can it be done? 

Many thanks for your time and your help, much appreciated! 

Adrian Cuthbertson

unread,
Dec 29, 2015, 11:54:12 AM12/29/15
to julia...@googlegroups.com
Julia's module system is very flexible. Check out Modules in the (0.4) manual and also include, import, export, using, require, reload, whos, workspace, current_module and probably some other related entries - it can all be a bit confusing :).

Here's an example which may do what you're looking for:

$ cat fi_0.jl
module M0
    include("fi_1.jl")
    include("fi_2.jl")
end

$ cat fi_1.jl
module M1
    foo()="I'm foo"
end

$ cat fi_2.jl
module M2
   foo()="I'm foo too"
end

$ julia -q
julia> include("fi_0.jl")
M0
julia> M0.M1.foo()
"I'm foo"
julia> M0.M2.foo()
"I'm foo too"

-- Adrian.

Adrian Salceanu

unread,
Dec 29, 2015, 12:16:40 PM12/29/15
to julia-users
Thanks Adrian - that's a nice way to do it, much appreciated. 

If I'm not wrong, it's similar to what the manual says when it mentions mixins? Read about it but haven't realized it could be used to this effect :) 

The approach I went with for now is to use convention over configuration, mapping folder structure to modules names (also a common pattern in other places). Mentioning it in case someone else runs into the same problem, as an alternative. 

With a structure like this, framework code would go into lib/jinnie with modules named Jinnie_App, Jinnie_Packager, Jinnie_Router. While the user code would go into app/ 

tree .
.
├── app
  ├── controllers
  ├── models
  └── views
├── bin
├── config
  └── routes.jl
├── config.jl
├── db
├── doc
├── lib
  ├── jinnie
    ├── app.jl
    ├── packager.jl
    └── router.jl
  └── tasks
├── log
├── packages.jl
├── public
├── test
├── tmp
└── vendor


16 directories, 6 files

Then in config.jl 

push!( LOAD_PATH, abspath(".") )
push
!( LOAD_PATH, abspath("./config") )
push
!( LOAD_PATH, abspath("./lib/jinnie") )

and from there on, "using". 

This ends up providing unique module names which visually indicate the hierarchy can be reversed to transform the names into paths. 

Adrian Cuthbertson

unread,
Dec 29, 2015, 12:28:37 PM12/29/15
to julia...@googlegroups.com
You'll tend to find julia modules are organised around types and implementations rather than modules. Have a look at https://github.com/JuliaStats/Distributions.jl as an example of a pretty complex package with many types and implementations and only one module. But the approaches are evolving all the time :).

Adrian Salceanu

unread,
Dec 29, 2015, 1:08:04 PM12/29/15
to julia-users
I see, that's interesting! Only Distributions.jl defines a module and the rest of the files are included and "scoped" in. 

Thanks for your help, much appreciated! 
Reply all
Reply to author
Forward
0 new messages