Learn With Me: Elixir - Calling Erlang Functions From Elixir (#55)

As we know, Elixir runs on the Erlang VM and Elixir code gets compiled into Beam bytecode so that it can run alongside and interact with Erlang code. Erlang has been around a lot longer than Elixir, so has accumulated a lot of libraries and functionality that don't yet exist in Elixir libraries. This means that you may occasionally have to reach out and call Erlang functions when the functionality you need exists in Erlang, but not in Elixir.

Let's learn how to make a call to the Erlang math library, which doesn't appear to have an equivalent in Elixir. The documentation for the Erlang Math library is available for us to look at. I urge you to look at it to see what Erlang documentation looks like. You may notice that the Elixir documentation appears to be significantly better than the Erlang documentation.

The documentation for the math module doesn't even have a description of what these functions do, although I can guess at many of them from the name. In clicking around, I've found that some other modules have much better documentation, so I'm not sure why the math module is so poorly documented. Even in when looking at the Erlang modules with better documentation, I find that the documentation standards in Elixir are much higher.

Erlang modules are all lower-case, so when you refer to an Erlang module, you refer to it as a lower-case atom. All modules in Erlang are referred to using atoms. I think one of the reasons Elixir wants modules to be upper-case is so they won't conflict with the Erlang modules. After all, Elixir modules are translated into Erlang VM modules during compilation, so they too are referred to in the compiled code using an atom.

Here's an example of calling the math.pow and math.sin functions in Elixir. It doesn't look all that different from calls to Elixir functions, with the biggest difference being that an atom is used to reference the module.

iex> :math.pow(3, 3)
27.0
iex> :math.pow(3, 4)
81.0
iex> :math.sin(0.5)
0.479425538604203
iex> :math.sin(180)
-0.8011526357338304
iex> :math.sin(580)
0.9300838049771285
iex> :math.sin(360)
0.9589157234143065
iex> :math.sin(1)
0.8414709848078965
iex> :math.sin(0)
0.0		

By comparing the results to a calculator, I see that :math.sin/1 expects radians and not degrees, but I never would have known that from reading the Erlang documentation.

Note that you will have to be aware of some of the differences between Elixir and Erlang when you make calls to Erlang. Erlang, for example, doesn't use binaries for strings, but character lists. You have to convert between strings and character lists when interacting with Erlang.

So even though I know nothing very little about the Erlang language, it wasn't difficult to call some of the Erlang library functions. At this point, I don't expect that I will be calling Erlang functions very often, but I probably will have to on rare occasions. I imagine that making calls to Erlang was a lot more common in the early days of Elixir when Elixir had relatively little functionality compared to today, and I suspect that it will slowly become less and less common over the coming years as the Elixir ecosystem continues to improve and libraries continue to be added.

Indeed, it would not be difficult to create an Elixir library that wraps the Elixir math functions. In fact, it would not surprise me if someone has done that already. Let's see... Ah, there we go! With a little searching, I was unable to uncover a Math library for Elixir. The changelog for it shows that it started off as just a simple wrapper around Erlang's math library, but it had some functions added to it later on.