`import` can’t load just-defined modules? Can’t re-`export` in-module functions?

question

#1

I’m making a little Julia app: in foo.jl I have,

println("Hi!")

Then I realize I have some more functionality to add and I want it to be in its own module for code reuse. So in this directory, I create bar/src/bar.jl and in there I put the following:

module bar

function bar1(n)
  return n + 1
end

export bar1

Then back in foo.jl (my script/app) I add

push!(LOAD_PATH, ".")
import bar
println(bar.bar1(10))

Running julia foo.jl I am happy to see:

Hi!
11

So far so good.

(Foreshadowing: the problem starts here.)

Now I realize I want to add some more functionality to module bar and but I want this new functionality to be in its own file-level module. Again, for code reuse—it’s probably my Node.js background, we made leftpad a module. So I make bar/src/baz.jl and in it I put:

module baz

function baz1(n)
  return n * 2
end

export baz1

end

Back in bar/src/bar.jl, I replace the export line with the following:

include("baz.jl")
import baz            # <-- error 1
export bar1, baz.baz1 # <-- error 2
  1. I can’t import baz, even though I’ve just defined it through include. Julia suggests I Pkg.add("baz"), complecting modules and packages.
  2. The second, more minor, point, is that export baz.baz1 is a syntax error—I can’t have . in export lines.

I can fix both these problems like this:

include("baz.jl")
baz1 = baz.baz1
export bar1, baz1

I can successfully use bar.baz1 in foo.jl. This tells me Julia knows about module baz after I include its source file, so, why can’t I import it? I’m a pro-import-anti-using partisan, because I like being able to know, in any given file, which module any non-base function/type comes from (blame my Python background, from numpy import * is a no–no), so I’d like that import baz there.

Question 1 Is there a way to import baz here? Edit: yes, import .baz!

Question 2 Are there historic reasons for why export baz.baz1 is a syntax error (LoadError: syntax: extra token "." after end of expression)? I would love to be able to re-export functions without having to create local shadows of them, i.e., baz1 = baz.baz1; export baz1 as I had to do above.


#2

Ah. Reading the modules docs more closely, I see I can solve my question #1 with:

import .baz # notice the dot 😄!

Great!!! I’ll leave this question open to get insight into my #2, why I can’t export baz.baz1.


#3

No. the thing you export will always be a field of the module which is a global variable in the module. So in your case baz.bar1 has to exist which means bar1 has to be in module baz. Convenient syntax for reexporting/conditional (sub)modules are the kind of related features we want. Changing how export / name resolution work doesn’t seem to worth doing unless there are very convincing cases where it can’t be done otherwise.


#4

Thanks for weighing in!

Am I reading this to mean export baz.baz1 should work? Because in my example, baz1 is in the module baz, but that syntax was unacceptable. Am I missing something?


#5

s/baz/bar/