A colleague of mine has just noticed some behavior relating to using and import which we found surprising.
include will load a file from disk and (effectively) insert the code at the point where the include line ran.
We were not aware that using and import could load code files from disk.
It seems that they can. I don’t recall reading anything about this in the documentation and having a quick search through the section on modules I didn’t find anything about this either.
Here is an example which shows what we have discovered.
Directory structure
tmp/
JuliaProject/
main.jl
MyModule.jl
Example
# MyModule.jl
println("my module")
julia> using MyModule
my module
Is anyone able to clarify? Should we have found this behavior surprising?
From my point of view, I thought that the way to combine multiple source files together was using an include statement. In other words, this statement allows splitting one source file into multiple files.
I also thought that import and using were statements which related to the importing of modules (namespaces) from one namespace path to another.
It’s in a different spot talking about packages, which uses modules for the necessary encapsulation: Code Loading · The Julia Language
The import statements for packages do not use leading dots.
To be frank, I’ve never used this form of defining a package, where the main “entry file” is just in some directory. It’s specifically the first point for the “Package Directories” list:
I always use an explicit src/X.jl form, to keep things more consistent and easier to navigate.
A package directory is a directory containing the source trees of a set of packages as subdirectories, and forms an implicit environment. If X is a subdirectory of a package directory and X/src/X.jl exists, then the package X is available in the package directory environment and X/src/X.jl is the source file by which it is loaded.
Package loading: e.g. import X or using X. The import mechanism allows you to load a package—i.e. an independent, reusable collection of Julia code, wrapped in a module—and makes the resulting module available by the name X inside of the importing module. If the same X package is imported multiple times in the same Julia session, it is only loaded the first time—on subsequent imports, the importing module gets a reference to the same module. Note though, that import X can load different packages in different contexts: X can refer to one package named X in the main project but potentially to different packages also named X in each dependency. More on this below.
However this is not the complete story. Perhaps someone can help fill in the gaps?
If I run using MyModule, then Julia will search for several things:
MyModule.jl/src/MyModule.jl
MyModule/src/MyModule.jl
MyModule.jl
I think all of the above are searched (from the current working directory).
However, I think there are also other alternative paths - but I don’t recall the details.
Can anyone help to fill in the gaps or direct me to a doc page about this?
Package directories
Package directories provide a simpler kind of environment without the ability to handle name collisions. In
a package directory, the set of top-level packages is the set of subdirectories that “look like” packages. A
package X exists in a package directory if the directory contains one of the following “entry point” files:
• X.jl
• X/src/X.jl
• X.jl/src/X.jl
So I wasn’t imagining this. Let me check my LOAD_PATH.
Julia related environment variables typically start with “JULIA_”, e.g. “JULIA_LOAD_PATH” or “JULIA_NUM_THREADS”. And versioninfo() does display all environment variables with this prefix.