The standard behavior is that names from Base are accessible as properties of normal modules.
julia> module Foobar end
Main.Foobar
julia> Main.Foobar.:*
* (generic function with 237 methods)
Do we like this? It seems a bit odd to me: They don’t appear in names(Main.Foobar; all=true) or propertynames(Main.Foobar), so I wouldn’t expect them to be properties. The alternative would be that the names are accessible from within Foobar but aren’t actually properties of it.
Yes, I expect to access imported names (like FooBar importing * from Base) with dot syntax. Unfortunately, names isn’t good at showing those. The imported keyword doesn’t work for implicit imports or explicit imports with using:
julia> module A
module B
export b, c, d
b = 1; c = 2; d = 3
end
using .B
using .B: c
import .B: d
end
Main.A
julia> A.b, A.c, A.d
(1, 2, 3)
julia> names(A;imported=true)
2-element Vector{Symbol}:
:A
:d
Ironic because explicit imports with using are now more recommended than with import so that module qualification protects against unintended method definitions on imported functions like it always protects against unintended reassignment of imported variables.
That just seems intuitive to me when imported names exist at all. If you want to make a new function particular to FooBar, it should be done in the module itself with no qualification.
julia> module Foobar end
Main.Foobar
julia> @eval Foobar (*)(a::Symbol, b::Symbol) = Symbol(string(a,b))
* (generic function with 1 method)
I would agree that it’s ideal that qualified modules are exactly the origin module, but that’s necessary for reassigning global variables at the moment and it’s a pain when modules get nested. Seems good enough just specify one imported module without going down the whole import chain.