A couple of days ago, someone opened a ticket on Elixir issues tracker saying it doesn't work on Windows:
I have since then verified the bug and I am working to address it.
Unfortunately, we will have to change current semantics. Fortunately, we have found it now and not too late.
This e-mail is to document the issue and the solution I have in mind before implementing it. Feedback is welcome.
## Understanding the root cause of the issue
In order for hot code swapping and code loading to work "thread safe", Erlang is responsible to load all modules byte code.
This is done by Erlang code server.
The Erlang code server has a series of paths it searches to find a module and it maps the module name to the filename.
That said, if you have an Erlang module named lists, you need to have a lists.beam bytecode file.
Since Elixir's goal is to stay as close to Erlang as possible when it comes to semantics, we have decided to follow the same approach.
That said, a module in Elixir named Foo::Bar, is written to ::Foo::Bar.beam bytecode file.
The issue arises because Windows does not accept ":" as a valid filename and therefore cannot compile any file.
We could fix this issue by providing a custom code server, but that would be steering away from Erlang and can introduce issues in new Erlang versions.
Another option is to make Foo::Bar generate a module name "Foo__Bar" (replacing Foo__Bar by underscores).
This would work fine but it would generate an impedance in the code since Foo::Bar no longer returns the atom ::Foo::Bar.
## A viable solution
One possible solution to the problem is to change modules lookup from "Foo::Bar" to "Foo.Bar".
This has one downside: it overloads the meaning of the operator "." but it would work fine in all other aspects.
Since we can address the overloading at compile time, it also shouldn't affect runtime performance.
As consequence files won't be compiled to a flat structure anymore, but a file hierarchy.
For example, today Foo::Bar is compiled to ebin/::Foo::Bar.beam.
With this proposal, Foo.Bar will be compiled to ebin/__MAIN__/Foo/Bar.beam. __MAIN__ will be Elixir's root namespace.
This change should not affect anything in practice (it doesn't affect how your code is run, just Elixir's compilation internals).
## Summing up
I am proposing to change Elixir's constants from Foo::Bar to Foo.Bar to fix a Windows issue.
Except that Foo::Bar is going to be deprecated, it should not affect any real code.
If you see downsides in this approach or if you can think of better solutions, please make yourself heard. Feedback is welcome.
Thanks,
José Valim
Founder and Lead Developer