Creating modules in Julia v0.7-alpha

I’m very confused on how to create a new module in Julia v0.7. Even the following doesn’t work:

julia> module Foo
       end
Main.Foo

julia> using Foo
ERROR: ArgumentError: Module Foo not found in current path.
Run `Pkg.add("Foo")` to install the Foo package.
Stacktrace:
 [1] require(::Module, ::Symbol) at ./loading.jl:868

Another issue: I have a new package Foo I’ve created with file .julia/dev/Foo/src/Foo.jl consisting of:

module Foo
using Base
# using LinearAlgebra
end

This works fine. But if I uncomment using LinearAlgebra I get the error:


julia> using Foo
ERROR: LoadError: ArgumentError: Module LinearAlgebra not found in current path.
Run `Pkg.add("LinearAlgebra")` to install the LinearAlgebra package.
Stacktrace:
 [1] require(::Module, ::Symbol) at ./loading.jl:868
 [2] include at ./boot.jl:314 [inlined]
 [3] include_relative(::Module, ::String) at ./loading.jl:1071
 [4] _require(::Base.PkgId) at ./loading.jl:997
 [5] require(::Base.PkgId) at ./loading.jl:878
 [6] require(::Module, ::Symbol) at ./loading.jl:873
in expression starting at /Users/sheehanolver/.julia/dev/Foo/src/Foo.jl:3

Even though other packages I have installed also call using LinearAlgebra.

An update: I sort of figured out how to solve the second problem:

  1. Delete all references to Foo.jl in .julia
  2. In a new location, run generate Foo in Pkg mode
  3. cd into the new Foo directory
  4. Call add LinearAlgebra in Pkg mode
  5. Copy-and-paste the existing src code that called using LinearAlgebra inside of Foo
  6. ^D out of julia so it forgets I ever ran using Foo (how dare I!!)
  7. Open a new julia session
  8. cd again into the new Foo directory
  9. Now call using Foo and it works!
  10. There is no step 10

I haven’t figured out how to get using Foo to work without first cding into its directory… make a link in .julia/dev didn’t work.

It actually not related to the version. When you create a module in current scope, you need to load it as a local module:

module Foo
end

using .Foo

or just use its full path

using Main.Foo

It actually not related to the version

Not sure what you mean, this is definitely new to Julia v0.7:

julia> versioninfo()
Julia Version 0.6.2
Commit d386e40c17 (2017-12-13 18:08 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin17.3.0)
  CPU: Intel(R) Core(TM) i5-7600K CPU @ 3.80GHz
  WORD_SIZE: 64
  BLAS: libgfortblas
  LAPACK: liblapack
  LIBM: libopenlibm
  LLVM: libLLVM-3.9.1 (ORCJIT, broadwell)

julia> module Foo end
Foo

julia> using Foo 

julia> 

Oh, sorry, didn’t notice this, I was wrong. I think this is about make things consistent.

in julia, everything is evaluated in module Main, and if the module is defined inside it, it should either
provide a relative path or an absolute path. In v0.6 if you define a module by yourself

module Foo

module Foo2
end

using Foo2
end

this will be wrong. You should use

module Foo

module Foo2
end

using .Foo2
end

and in REPL, what you write is actually inside module Main, therefore, it should use relative path or absolute path.

1 Like

OK, I think I figured it out:

(v0.7) pkg> add /path/to/Foo.jl

(v0.7) pkg> develop /path/to/Foo.jl

Then I can call using Foo without being in the right directory.

Should be no need to add first.

Why do you think it would be better to do pkg> develop /path/to/Foo.jl rather than pkg> add /path/to/Foo.jl? (I am just trying to understand the philosophy of the package manager.) Thanks.

The way add local_repo_path#branch works is exactly the same as add external_repo_url#branch. Track the git repository at the path / url and use update to get new commits on the branch you track.
Note that only using add means that your project has an immutable state and will work the same whenever you get back to it.

dev is used when you want to point to a path and use the (mutable) state of the files there. There is no longer any guarantee that the project will work the same next time you get back to it, the files are no longer considered immutable and might have been changed since last time you used the project.

1 Like

How does it choose which version to use? I.e. the one in dev/ vs one in packages/?

If the manifest has a path entry it uses that path. If the manifest does not have a path entry the path is computed based on git-tree-sha and is loaded from packages. dev puts a path entry into the Manifest.

OK, I think I understand. .julia/environments/v0.7 is the default “project”, but is otherwise treated the same as all other projects. If I was stubborn and wanted to manage the packages available by hand, I would need to edit Manifest.toml by adding

[[Foo]]
deps = ["LinearAlgebra"]
path = "/path/to/Foo.jl"
uuid = "?????"
version = "0.0.0"

Where I would somehow need to figure out the UUID of Foo.jl. What typing

(v0.7) pkg> develop /path/to/Foo.jl

does is adds these lines, with the correct UUID, to Manifest.toml

Ojn the other hand,

(v0.7) pkg> add BenchmarkTools

just adds

[[BenchmarkTools]]
deps = ["Compat", "JSON"]
git-tree-sha1 = "ea054fbc1f71dd1544b0c4dc5623e059aba288c0"
uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
version = "0.3.1"

that is, it doesn’t specify a path, so instead of loading from the specified path, it loads from .julia/packages/, using the UUID and version to choose the right package. If then type

(v0.7) pkg> develop BenchmarkTools

it clones BenchmarkTools.jl to .julia/dev/BenchmarkTools, and modifies Manifest.toml by adding path = ~/.julia/dev/BenchmarkTools, so using BenchmarkTools looks for the package at the specified path.

3 Likes

Yes, good summary.