The expression include("source.jl") causes the contents of the file source.jl to be evaluated in the global scope of the module where the include call occurs. If include("source.jl") is called multiple times, source.jl is evaluated multiple times.
Also we need two lines of code for module import instead of just one - include and using.
Is there any way to reduce module imports to one line - using .Hello: helloworld?
In this context: is modifying LOAD_PATH to include the current project a viable thing? How and where would I want to modify this path locally inside my project?
I think what you’re doing there is the best way to do it. Sure, the include evaluates the module in top-level scope, but that is not an issue - you actually want the Helper module to be available at the top level.
It’s true that it does require both include and using. This is because the two statements do different things: include is about where to find the source code file, and using is about which names to bring into the scope of Main.
As far as I know, there is no way to force Julia to conflate files with modules. That is, you can’t have it automatically add modules to your different source files. I would argue it doesn’t add any benefit, either.
You could skip the module in helper, then you would just bring all the things from the helper file into scope with the include, no need for using. Though if you want it to be a separate namespace this will not allow for that.
To Julia, files and modules are two very different things. A file can define multiple or no modules at all. A module can span multiple files.
That said, I have export JULIA_LOAD_PATH=".:$JULIA_LOAD_PATH" in my shell profile. With that, import X will look for a file X.jl in the directory from which Julia was launched and load the module therein defined. That mimics Python’s behavior I think.
Discovery is case-sensitive, so you would need to rename helper.jl -> Helper.jl.
And for the sake of completeness: if you do want a separate namespace, then you can skip the using line, since by include-ing the file that defines the module Helper, it’s already available to use. So, modifying your main.jl:
# using .Helper: helloworld # <- This is not needed
Helper.helloworld() # `helloworld` is not imported
The general purpose of @isdefined is clear. What I meant is that I don’t see the point of this pattern:
(@isdefined Dates) == false ? using Dates : nothing
# more code ...
With module MyDates you are creating a brand new module with its own namespace; almost nothing is defined there, except Base, eval, include and friends. So Dates will never be defined at that point, and the condition @isdefined Dates will always return false. It doesn’t matter if the script "mymod.jl" that contains that code had been executed before in that session.
If that were the case, executing it again will create another module also called MyDates (there will be a warning about that), where Dates is not defined at the outset either.
“current active environment” refers to the dependency graph as defined in the Project.toml and Manifest.toml.
Why doesn’t this work though, when there is a Project.toml file inside testproj project folder
With a Project.toml you commit to reproducibility. I believe the relevant passage from the manual is
Which dependencies a package in a package directory can import depends on whether the package contains a project file:
If it has a project file, it can only import those packages which are identified in the [deps] section of the project file.
One part of ensuring reproducibility is to avoid name clashes. Any dependency (i.e. anything loaded with import or using) needs an UUID for that reason. But that is quite simple. If the code in Helper is capsuled from the rest, then make it it’s own package. From the REPL you can generate a bare-bones structure with
That will make directories Helper and Helper/src, generate a uuid, write it to Helper/Project.toml, and an entry point Helper/Helper.jl defining the module.
You can now add this package to the main project: ]dev ./Helper
Then again, including Helper.jl multiple times might not be that bad. Depends on what’s in it really.
If that’s too much hassle, but you still want another than the default environment, which is always a good idea, you can make one in a folder different from TestProj and use that. That’ll keep the Project.toml out of TestProj.