Seeking more extensive docs on module/using/import


#1

Suppose I have a module U of utility routines that are used by module A, which has my application. These are in files called u.jl and a.jl respectively. How do I include the utility routines in the application? It seems that there are at least four choices: (1) I can make a package and put U in the package, (2) I can include U from the repl, (3) I can put an include u.jl statement in a.jl, but before the module A declaration, (4) I can put include u.jl inside a.jl inside the module A declaration. In each of these cases except the first, the setting of LOAD_PATH plays a role. In each of these cases, I need appropriate using or import statements. The cases behave differently when I make a change to u.jl while debugging a.jl. And possibly precompilation also matters.

Which of these solutions is the best? I’ve found my own solution which seems to be OK, but I would have trouble explaining these choices to someone else. An issue here is that the documentation on modules in the Julia manual is not as in-depth as the other sections. Could I request that a Julia developer who knows this material well write a more extensive commentary for that section of the manual?


#2

I always make a package, and let it live in .julia/VERSION/. Even for things that are used by a single project. When Pkg3 comes out, I will consider putting them in some other directory, but I have no strong reasons to do so (except that I need to migrate manually when a new version of Julia comes out).


#3

Tamas,

This is a reasonable solution, although different from the one I adopted. However, just to clarify my request, I am not actually seeking a specific software design pattern. Rather, I am seeking a greater understanding of how module, using, and import, LOAD_PATH and recompilation work, and how they are intended to be used in a typical small-project environment. Like many participants in this discourse site, I teach at a university, so I need to be able to explain aspects of Julia to students even if I’m not using them.

– Steve Vavasis


#4

My understanding is that the current package system is under redesign:


so I am not sure I would spend too much time with students on the details.

However, I am in a similar situation (will teach Julia soon), and this is what I would explain in the first pass (hopefully someone more knowledgeable will come along and fill in the details):

  1. Packages are a distribution channel (“files on a disk”). Pkg helps you manage these (update, check out branches, resolve dependencies, etc). Packages are orthogonal to modules, mostly.
  2. import X and using X search LOAD_PATH for module X, and load it into the image. import X merely makes the module name available. using X also makes the names it exports available. import X: foo allows you to add methods to X.foo without prefixing, but that’s just a convenience, you can use X.foo.
  3. modules are namespaces, and have nifty features such as submodules etc, pretty well explained in the docs. Namespaces are useful for organizing your code.

Regarding (re,pre)compilation: my mental model is that modules are compiled when loaded, except when they were used and precompiled before. If everything works out, I tend to think of that as a speed gain, not something that should affect things. I would perhaps not talk about this in a class unless it is specifically about programming.

The advantage of the workflow I outlined above is that

  1. the students don’t need to touch LOAD_PATH, or even know about it,
  2. PkgDev.generate will put everything in the right place, so packages are very cheap to create.