Nice resume, all that seems perfectly correct (and helpful).
I think the way to think about these things is about namespaces.
import A: func
brings func
to the namespace where that was executed. If that namespace is module B
, then B.func
is available. If inside module B
you add export func
now, func
is available where using B
was executed.
using A
will put then func
into the current namespace if it is exported in A
(the same thing as above). If that was executed inside module B
, now B.func
exists.
import A
does not bring A.func
into the namespace, thus if that was executed inside module B
, there will be no B.func
.
(I don’t think you can import or export one method but not the other, of the same function. That is one of the reasons type piracy is highly discouraged).
Concerning the “bug”: actually the problem there is that Julia does not complain of a module exporting something that is not defined (it can’t really do that, because the module is parsed sequentially, thus it cannot know if there will be a definition later). A linter could possibly do that. But here the REPL does not seem to try to autocomplete, while B.<tab>
does (with a stranger name that does not overlap with any other function that is clearer):
julia> module B
export foobar
end
Main.B
julia> foo # tab (nothing appears)
julia> B.foobar # does autocomplete
ERROR: UndefVarError: foobar not defined
Stacktrace:
[1] getproperty(x::Module, f::Symbol)
@ Base ./Base.jl:35
[2] top-level scope
@ REPL[2]:1