How can I load two packages with the same name but located in seperate folders?
Example:
/src/alpha/foopackage.ads
/src/beta/foopackage.ads
I then would like to use foopackages using:
with alpha.foopackage;
with beta.foopackage;
Also, if you have any other tips about organizing projects in Ada please write. There is not much info about project organization in Ada on the net.
You've already solved the problem!
src/alpha/foopackage.ads contains:
package alpha.foopackage is
...
end alpha.foopackage;
while src/beta/foopackage.ads contains:
package beta.foopackage is
...
end beta.foopackage;
Now you will run into a temporary problem if you're using GNAT and its default naming convention. This naming convention requires that the files be named alpha-foopackage.ads and beta-foopackage.ads, respectively.
If you insist on using foopackage.ads as the filenames, this convention can be worked around. With GNAT, see Handling Arbitrary File Naming Conventions with gnatname, Using Other File Names, or Alternative File Naming Schemes.
This is almost a duplicate of the question which led to this answer.
However, there's another issue to do with naming, which is that GNAT (I think you are using GNAT?) has a default file naming convention (there are ways of overriding this convention, but you'd need a Good Reason to bother).
So your source files, whatever directory you choose to put them in, should be named alpha-foopackage.ads and beta-foopackage.ads respectively.
Related
I am trying to correctly configure julia project.
The project had initially:
One module in its own directory
Another "kind of module" in another directory, but there was no module keyword and it was patched together with help of includes.
A few files in the root to execute it all by just running "julia run.jl" for example.
No packages, no Project.toml no Manifest.toml - there is "packages.jl", which manually calls "Pkg.add" to for preset list of dependencies.
Not all includes were used to put it all together, there was some fiddling with LOAD_PATH
Logically the project contains 3 parts that I see there and something as I would see as "packages" in for example python world.
One "Common" module with basic util functions shared by all interested modules.
One module A, which has dependency on "Common".
Module B, which has dependency on A and "Common".
What I did is, I created 3 modules in their separate directories and to put it all together. These modules make sense internally and there is no real reason to expose them "outside". The whole code is in the end executable and there would be exposed probably just one function, that executes everything. I created loader file, which included all 3 module files. That way I got rid of LOAD_PATH and references in IDE started to work. This works for our purposes, but still isn't ideal. I have been reading quite a lot about Julia structure and possibilities - modules, packages, but still don't understand fully. And Revise doesn't work.
Is it correct to have modules like this? I like modules as they clearly set boundaries between modules using export lines.
I would also like to make the code as compatible with IDE as possible (LOAD_PATH settings didn't work for VS code and references to functions were broken) and also with Revise.
What is the typical structure for this?
How to clearly separate code while make the development easy?
How to make this work with Revise?
I expect it's good idea to make a package for this, but should I make it for the whole project? Then it would mean one "project" module and 3 submodules A, B and Common?
Or should it be 3(4) packages per module?
Thanks for any output. Comparison of some of the principles to Python/Java/kotlin/C#/Javascript module/packages could be helpful.
In CubicEoS.jl I've made a single package which provides two modules: CubicEoS with general algorithms and CubicEoS.BrusilovskyEoS with an implementation of necessary interface to make CubicEoS works on a concrete case. The last module depends on the first. Revise works well. As a user (not developer) of CubicEoS, I have scripts which run some calculations.
So, in your case, I would create a single package with four modules. The forth module is a hood for the others: Common, A and B. The possible file structure maybe like this
src/
TheHood.jl
Common/Common.jl
Module_A/Module_A.jl
Module_B/Module_B.jl
test/
...
examples/ # those may put out of here, but the important examples may be in test/
...
Project.toml
And, the possible module structure may be like this
# TheHood.jl
module TheHood
export bar
include("Common/Common.jl")
include("Module_A/Module_A.jl")
include("Module_B/Module_B.jl")
end
# Common/Common.jl
module Common
export util_1, util_2
using LinearAlgebra
util_1(x) = "util_1's implementation"
util_2(x) = "util_2's implementation"
end
# Module_A/Module_A.jl
module Module_A
import ..Common
export foo
foo(x) = "foo's implementation"
end
# Module_B/Module_B.jl
module Module_B
import ..Common
import ..Module_A
export bar
bar(x) = "bar's implementation"
end
Now, I'll answer the questions
What is the typical structure for this?
If the modules does not use independently, I would use the structure above. For small projects I've found "one package = one module" strategy painful when a core package updates.
How to clearly separate code while make the development easy?
In Julia, a module effectively is a namespace. In inner modules (like A, B, Common), I usually import the dev-modules, but use modules which a dev-module depends on (see above using LinearAlgebra vs import ..Common. That's my preference to clarify names.
How to make this work with Revise?
Turn the code into a package. That's preferable, because Reviseing of standlone modules is buggy (at least, in my experience). I'm usually using Revise like this
% cd where_the_package_lives # actually, where the project.toml is
% julia --project=. # or julia and pkg> activate .
% julia> using Revise
% julia> using ThePackage
After that I usually can edit source code and call the updated methods w/o restarting of the REPL. But, Revise has some limitations.
I expect it's good idea to make a package for this, but should I make it for the whole project? Then it would mean one "project" module and 3 submodules A, B and Common?
Or should it be 3(4) packages per module?
You should separate "scripty" (throughaway or command line scripts) and core (reusable) code. The core I would put in a single package. The scripty files (like examples/, CLI programs) should be alone using the package. The scripty files may define modules or whatever, but their users are endusers, not developers (e.g. running a script involves an i/o operation).
Just to end this.
The main thing I was missing and would save me a lot of time if I knew:
If you have your own package, it means the file src/YourPackage.jl will be "imported/included" once "using" keyword is being used and everything just works. No need to do any kind of import/LOAD_PATH magic.
just doing that fixed 95% of my problems. I ended up following patterns in accepted answer and also from the comment recommending DrWatson.
Only small thing is the fact that "scripts" don't work well with VSCode. "find all references" or "go to definition" and autocomplete don't work. They do work for everything within "YourPackage.jl" and it's imports perfectly and so does Revise. It's really tiny thing since scripts are usually like 3 lines of code.
I have a module I wrote here:
# Hello.jl
module Hello
function foo
return 1
end
end
and
# Main.jl
using Hello
foo()
When I run the Main module:
$ julia ./Main.jl
I get this error:
ERROR: LoadError: ArgumentError: Hello not found in path
in require at ./loading.jl:249
in include at ./boot.jl:261
in include_from_node1 at ./loading.jl:320
in process_options at ./client.jl:280
in _start at ./client.jl:378
while loading /Main.jl, in expression starting on line 1
There is a new answer to this question since the release of Julia v0.7 and v1.0 that is slightly different. I just had to do this so I figured I'd post my findings here.
As already explained in other solutions, it is necessary to include the relevant script which defines the module. However, since the custom module is not a package, it cannot be loaded as a package with the same using or import commands as could be done in older Julia versions.
So the Main.jl script would be written with a relative import like this:
include("./Hello.jl")
using .Hello
foo()
I found this explained simply in Stefan Karpinski's discourse comment on a similar question. As he describes, the situation can also get more elaborate when dealing with submodules. The documentation section on module paths is also a good reference.
EDIT: Updated code to apply post-v1.0. The other answers still have a fundamental problem: if you define a module and then include that module definition in multiple places, you will get unexpected hard-to-understand errors. #kiliantics' answer is correct as long as you only include the file once. If you have a module that you're using across multiple files, make that module into a package, use add MyModule, and then type using MyModule in as many places as you want, letting Pkg handle module identity for you.
Though 张实唯's answer is the most convenient, you should not use include outside the REPL (or just once per included file as a simple practice to organize large modules, as in the first example here). If you're writing a program file, go through the trouble of adding the appropriate directory to the LOAD_PATH. Remy gives a very good explanation of how to do so, but it's worth also explaining why you should do so in the first place. (Additionally from the docs: push!(LOAD_PATH, "/Path/To/My/Module/") but note your module and your file have to have the same name)
The problem is that anything you include will be defined right where you call include even if it is also defined elsewhere. Since the goal of modules is re-use, you'll probably eventually use MyModule in more than one file. If you call include in each file, then each will have its own definition of MyModule, and even though they are identical, these will be different definitions. That means any data defined in the MyModule (such as data types) will not be the same.
To see why this is a huge problem, consider these three files:
types.jl
module TypeModule
struct A end
export A
end
a_function.jl
include("types.jl")
module AFunctionModule
using ..TypeModule
function takes_a(a::A)
println("Took A!")
end
export takes_a
end
function_caller.jl
include("a_function.jl")
include("types.jl") # delete this line to make it work
using .TypeModule, .AFunctionModule
my_a = A()
takes_a(my_a)
If you run julia function_caller.jl you'll get MethodError: no method matching takes_a(::A). This is because the type A used in function_caller.jl is different from the one used in a_function.jl. In this simple case, you can actually "fix" the problem by reversing the order of the includes in function_caller.jl (or just by deleting include("types.jl") entirely from function_caller.jl! That's not good!). But what if you wanted another file b_function.jl that also used a type defined in TypeModule? You would have to do something very hacky. Or you could just modify your LOAD_PATH so the module is only defined once.
EDIT in response to xji: To distribute a module, you'd use Pkg (docs). I understood the premise of this question to be a custom, personal module. It's also fine for distribution if you know the relative path of the directory containing your module definition from each file that needs to load that module, e.g. if all your files are in the same folder then you'd just have push!(LOAD_PATH, #__DIR__).
Incidentally, if you really don't like the idea of modifying your load path (even if it's only within the scope of a single script...) you could symlink your module into a package directory (e.g. ~/.julia/v0.6/MyModule/MyModule.jl) and then Pkg.add(MyModule) and then import as normal. I find that to be a bit more trouble.
This answer has been OUTDATED. Please see other excellent explanations.
===
You should include("./Hello.jl") before using Hello
This answers was originally written for Julia 0.4.5. There is now an easier way of importing a local file (see #kiliantics answer). However, I will leave this up as my answer explains several other methods of loading files from other directories which may be of use still.
There have already been some short answers, but I wanted to provide a more complete answer if possible.
When you run using MyModule, Julia only searches for it in a list of directories known as your LOAD_PATH. If you type LOAD_PATH in the Julia REPL, you will get something like the following:
2-element Array{ByteString,1}:
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4"
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/share/julia/site/v0.4"
These are the directories that Julia will search for modules to include when you type using Hello. In the example that you provided, since Hello was not in your LOAD_PATH, Julia was unable to find it.
If you wish to include a local module, you can specify its location relative to your current working directory.
julia> include("./src/Hello.jl")
Once the file has been included, you can then run using Hello as normal to get all of the same behavior. For one off scripts, this is probably the best solution. However, if you find yourself regular having to include() a certain set of directories, you can permanently add them to your LOAD_PATH.
Adding directories to LOAD_PATH
Manually adding directories to your LOAD_PATH can be a pain if you wish to regularly use particular modules that are stored outside of the Julia LOAD_PATH. In that case, you can append additional directories to the LOAD_PATH environment variable. Julia will then automatically search through these directories whenever you issue an import or using command.
One way to do this is to add the following to your .basrc, .profile, .zshrc.
export JULIA_LOAD_PATH="/path/to/module/storage/folder"
This will append that directory onto the standard directories that Julia will search. If you then run
julia> LOAD_PATH
It should return
3-element Array{ByteString,1}:
"/path/to/module/storage/folder"
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/local/share/julia/site/v0.4"
"/Applications/Julia-0.4.5.app/Contents/Resources/julia/share/julia/site/v0.4"
You can now freely run using Hello and Julia will automatically find the module (as long as it is stored underneath /path/to/module/storage/folder.
For more information, take a look at this page from the Julia Docs.
Unless you explicitly load the file (include("./Hello.jl")) Julia looks for module files in directories defined in the LOAD_PATH variable.
See this page.
I have Julia Version 1.4.2 (2020-05-23). Just this using .Hello worked for me.
However, I had to compile the Hello module before just using .Hello. It makes sense for both the defined and using scripts of Hello is on the same file.
Instead, we can define Hello in one file and use it in a different file with include("./Hello.jl");using .Hello
If you want to access function foo when importing the module with "using" you need to add "export foo" in the header of the module.
I am trying to follow closely #hadley's book to learn best practices in writing R packages. And I was thrilled to read these lines about the philosophy of the book:
anything that can be automated, should be automated. Do as little as
possible by hand. Do as much as possible with functions.
So when I was reading about dependencies and the (sort of) confusing differences between import directives in the NAMESPACE file and the "Imports:" field in the DESCRIPTION file, I was hoping that roxygen2 would automatically handle both of them. After all
Every package mentioned in NAMESPACE must also be present in the
Imports or Depends fields.
I was hoping that roxygen2 would take every #import in my functions and make sure it is included in the DESCRIPTION file. But it does not do that automatically.
So I either have to add it manually to the DESCRIPTION file or almost manually using devtools::use_package.
Looking around for an answer, I found this question in SO, where #hadley confirms in the comments that
Currently, the namespace roclet will modify NAMESPACE but not
DESCRIPTION
and other posts (e.g. here or here) where collate_roclet is discussed, but "This only matters if your code has side-effects; most commonly because you’re using S4".
I wonder:
the reason that DESCRIPTION is not automatically updated (sort of contradicting the aforementioned philosophy, which is presumably shared by roxygen2) and
If someone has already crafted a way to do it
I have written a little R package for that task:
https://github.com/markusdumke/pkghelper
It scans the R Code and NAMESPACE for packages in use and adds them to the Imports section.
The namespace_roclet edits the NAMESPACE file based on the tags added in the script before the function. As there are three types of dependencies (Depends, Imports, and Suggests), a similar method as used by the namespace_roclet would require three different tags (notice Imports should be a different one, to differentiate it from the packages to attach in NAMESPACE).
If you are willing to take a semi-automated process, you could identify the packages you have used and add the missing ones to DESCRIPTION, in the adequate sections.
library(reinstallr)
package.dir <- getwd()
base_path <- normalizePath(package.dir)
files <- list.files(file.path(base_path, "R"), full.names = TRUE)
packages <- unique(reinstallr:::scan_for_packages(files)$package)
packages
Regarding the two bullets you wonder about at the bottom:
Updates to the DESCRIPTION file could be further automated with additional roclets, however already >4 years ago such a pull request was deferred:
https://github.com/klutometis/roxygen/pull/76
I have to assume that the guys would indeed rather have you use the devtools package for updating the DESCRIPTION file, instead of adding this to roxygen2. So in that sense, devtools would be the first available choice
In the package inferred system, you can specify a dependency on a package of the form "a/b/c" where a is the package name and there is a lisp file at "b/c.lisp" that defines the "a/b/c" package.
Is there a way to specify a different path for the file for the package inferred system? For example say the file is at "src/b/c.lisp" instead of "b/c.lisp".
It's probably a bug that package-inferred-system uses system-source-directory instead of component-pathname. If you think it is, please file a bug against https://bugs.launchpad.net/asdf
Unhappily, bug or not, any fix isn't going to be released then made universal for a while. So at least for the next two years, you can't rely on it unless you provide your own fixed ASDF.
As for a workaround — why not place your .asd file in src/ if you want all source under there???
You can use register-system-packages to specify which packages a system provides. You can read more here
Since in http://julia.readthedocs.org/en/latest/manual/modules/ there's no much info about modules, I would like to ask the following.
I want to try two modules via ijulia. Both modules are in my working directory as
name-of-files.jul. I will call them generically module_1.jul and module_2.jul.
module_1.jul uses module_2.jul and I load it with
using module_2
On ijulia session, if I try
using module_1
gives an error. I also tried
include("module_1.jul")
This last sentence, when executed, rises an error because the module_1.jul cannot find
variable "x" that I know is contained in module_1.jul (in this case I "loaded" the module
using include("module2.jul") inside module_1.jul
Julias module system assumes some things that aren't necessarily obvious from the documenation at first.
Julia files should end with .jl extensions.
Julia looks for module files in directories defined in the LOAD_PATH variable.
Julia looks for files in those directories in the form ModuleName/src/file.jl
If using module_1 fails then I'm guessing it's because it's source files fail one of the above criteria.
Some time has passed since this question. Recently, Noah_S wrote the solution in the comments of the previous answer; this means that it is a recurrent doubt for people starting to learn the language. For their sake, I will re-write it here Noah_S' answer along with my most novel solution.
I am a mess with the julia versions and which commands work with the specific ones, so for older julia versions we have to look for the \path and then include in the julia module
push!(LOAD_PATH, "/path")
In newer versions this can be improved. Forget about looking by hand the path and just do
path = readstring(`pwd`)
push!(LOAD_PATH, chomp(path))
I hope this can be useful to many julians newcomers.