If `X` is a module, why `X.X` also refers to `X`?

What’s the point of this?

julia> module X end
Main.X

julia> X
Main.X

julia> X.X
Main.X

julia> X.X.X
Main.X

Because of this, I cannot define a function X() within X, for example.

I’m guessing the reason for this is that you sometimes want to specify X.foo() to distinguish from Y.foo(), even within the module X (for clarity).

The naming convention is to capitalize the module, but not the function. So a module Foo might provide the function foo. Modules that are named after a type that they provide use the plural, so the module Foos might provide the type Foo.

2 Likes

It’s possible that some use of it are not important anymore (e.g. it’s used sometimes in macros as incorrect hygiene and I’m pretty sure it was used in lowering). Do note that it is the reason you can use Main in the REPL though. (that one can be special cased if needed of course)

I find this to be a very neat feature when I use explicit imports (in packages) and want the module name imported for using functions/variables that I would not otherwise specify with using, eg

using Foo: Foo, bar
bar()     # available
Foo.baz() # qualified

Note that even if X.X didn’t refer to X, it would still be inconvenient to name the main function of module X as X(), because it could not be exported. (The module name and the function name would collide in the calling module.)

One could let modules have a “main function” that would be called using the module name. For example, like this:

(M::Module)(args...) = M.__main__(args...) # Type piracy.

module X
   function __main__(greeting)
       println(greeting, ", world")
   end
end

X("Hello")

(Of course, it’d be much cleaner if the function could be named X instead of __main__.)

I would find that pretty weird — the name X would refer to two different objects in the same namespace, depending on the context.

I am not sure what the use case is.

No. Look at my example code. The name X refers to the module. Only, modules would be callable, and calling a module would call it’s main function. To refer to the function you’d have to do X.__main__ (or X.X if it were possible to name the function that.)

I guess one use would be “mini-modules” that only export one single function.

1 Like

Thanks for explaining. It is rather clever.

But, as you noted above, this is not encouraged naming style: modules are capitalized, functions are not. And when the exported callable is a constructor, the module name should be plural.

1 Like

I think this recommendation came from the fact that you can’t define a type with the same name as the module it’s in.

Precisely — and my understanding is that even with the workaround of @Per, this restriction would continue to hold.