Actually, it’s really easy to create a “nicer” API layer for Erlang from Elixir:
defmodule :some_module do
def some_func(), do: 10
end
This can be called as some_module:some_func(). from Erlang, just like you would expect. It could probably be even integrated into the defmodule macro as an optional parameter like
defmodule SomeModule, alias: :some_module, do
(not sure whether I got the syntax right ).
I don’t think there is a need to make macros compatible, having a nice “ABI” in the form of modules that are simple atoms seems sufficient to me.
However, as said, independent of the language (Elixir is just one example here), the runtime library should IMO be available on Hex s.t. everything that understands hex packages can use modules written in the language without installing additional tooling (globally). I ran into this issue on the implementation of ierl (Jupyter kernel for Elixir, Erlang and LFE), as I could not generate a “self-contained” version without using mix to compile it, even though all code in there is Erlang code. Would have also been a lot easier to write the glue-code in Elixir instead of Erlang, but that’s essentially the same problem.
Well, hex has sadly no notion of binary artifacts, so this would be tricky for @lpil, though the gleam compiler could maybe be put into priv. For Elixir, this is actually not a problem, I think.
Love this thread, I’ve been thinking about this a lot over the years, and much of Gleam’s design was made with this in mind.
Gleam’s standard library is on Hex, largely so Hex can be used to manage all deps rather than needing the OS package manager for that.
I’ve not yet done the plumbing for this yet but soon published Gleam Hex packages will include the precompiled Erlang output and typespecs, so if you’re an Erlang or Elixir user you won’t need to install the Gleam compiler to make use of libraries written in Gleam. You might not even know you’re using Gleam if all goes to plan.
The compiler will only be required if you’re writing your own Gleam and thus need to type check your code against your Gleam dependencies.
At least for compilers written in Erlang its relatively easy to make a rebar3 plugin that pulls in the compiler as a dependency. All one needs to do is add the plugin to rebar.conf and one can compile files with a new languages endings.
IIRC you went to implement the compiler in Rust, so that path is a bit blocked right now. In my eyes also a learning for interop: write compilers so they run on the BEAM for better interop.
But if you bootstrap the Gleam compiler in Gleam you could upload it to hex again.
Once I’ve released the precompiled package feature (likely in the next release) then the only compiler required will be the Erlang one, so we don’t even need to self host
There is a TODO in there, but what I have done so far:
Running exerl:start(). will discover an existing Elixir installation using an elixir on the PATH, add it to the code path and start the elixir and logger applications
When used as a rebar3 plugin, it will discover .ex files in the lib and src directory and compile them (using the existing Elixir installation, in-process by directly calling Kernel.ParallelCompiler.compile_path)
exerl_download contains basic functionality to download and extract a precompiled Elixir release to ~/.local/share/exerl/elixir
What I want to do (because I need this for integration in an existing project):
Add a new resource type elixir that allows pulling in Elixir as a dependency using exerl_download, i.e. one would specify {elixir, "1.14.2"} and end up with the precompiled libs in _build
This should in particular work for escript building as well, I was pretty annoyed when building ierl that I could only get a self-contained escript using mix
The compiler should actually be usable, it’s very PoC right now
I’d also like to provide a replacement for rebar_mix that utilizes the loaded Mix modules instead of relying on the command-line interface
For @filmor and anyone else who might be interested. I’m looking to find someone interested in taking over rebar_mix. It has bugs and I’ve been unable to get a response from the current owner so feel it is time to take out what I consider the buggy parts.
To be honest, I’d like to first try my attempt here. I dislike that rebar_mix is shelling out, I’d like to see whether I can make this work purely in Erlang, integrating with the Mix modules directly and then suggesting a stable API to the Elixir devs to keep this working.
Sounds good. If it works it’d be great to make that the new rebar_mix. So just let me know if you are succesful and are then interested in moving it to rebar_mix.
It’s been a while since I had time to work on this, but today I’ve been for the first time able to compile GitHub - filmor/exerl_test: exerl_test which includes Explorer and Phoenix as deps.
A relatively simple thing would be direct support for structs. It is not difficult to do, just check my lightening talk from Code BEAM in Berlin, it just needs some syntax.
I know that structs are just maps so it isn’t really necessary but it makes working with Elixir modules so much easier and clearer as it is what Elixir uses. I added it to LFE for that reason.
One thing I have thought is the ability to automagically create native versions of a new module in the other beam languages. For example it would allow me, from Elixir, to do:
Erlang.Ets.insert(obj, table) # Notice the argument order is swapped to handle Elixir pipes
Or
elixir_task:async_stream(Fun, Enum)
Oh, and there should be as close to 0% effort required by the developer as possible (within reason, at minimum there needs to be a flag to enable it for a module).
Yes, I know that macros would be difficult to handle, as would chars vs Elixir strings, and protocols, and structs (see @rvirding’s post above) and maybe Erlang may need to support Elixir-like module namespaces. So perhaps the scope of such a feature should be limited. But it would be nice to be able to write a library in Elixir and have the other beam languages benefit too using their native syntax.
Yes. Each language should have a default prefix, so basically this could avoid most of module name clash between languages, and namespace could be overridden locally to avoid module name clash inside same language.