How do I run a beam file compiled by Elixir or Erlang?

Samuel Lampa picture Samuel Lampa · Aug 20, 2014 · Viewed 12.2k times · Source

I have installed Erlang/OTP and Elixir, and compiled the HelloWorld program into a BEAM using the command:

elixirc test.ex

Which produced a file named Elixir.Hello.beam

How do I run this file?

Answer

Alexei Sholik picture Alexei Sholik · Aug 21, 2014

Short answer: no way to know for sure without also knowing the contents of your source file :)

There are a few ways to run Elixir code. This answer will be an overview of various workflows that can be used with Elixir.

When you are just getting started and want to try things out, launching iex and evaluating expressions one at a time is the way to go.

iex(5)> Enum.reverse [1,2,3,4]
[4, 3, 2, 1]

You can also get help on Elixir modules and functions in iex. Most of the functions have examples in their docs.

iex(6)> h Enum.reverse

                        def reverse(collection)

Reverses the collection.
[...]

When you want to put some code into a file to reuse it later, the recommended (and de facto standard) way is to create a mix project and start adding modules to it. But perhaps, you would like to know what's going on under the covers before relying on mix to perform common tasks like compiling code, starting applications, and so on. Let me explain that.

The simplest way to put some expressions into a file and run it would be to use the elixir command.

x = :math.sqrt(1234)
IO.puts "Your square root is #{x}"

Put the above fragment of code into a file named simple.exs and run it with elixir simple.exs. The .exs extension is just a convention to indicate that the file is meant to be evaluated (and that is what we did).

This works up until the point you want to start building a project. Then you will need to organize your code into modules. Each module is a collection of functions. It is also the minimal compilation unit: each module is compiled into a .beam file. Usually people have one module per source file, but it is also fine to define more than one. Regardless of the number of modules in a single source file, each module will end up in its own .beam file when compiled.

defmodule M do
  def hi(name) do
    IO.puts "Hello, #{name}"
  end
end

We have defined a module with a single function. Save it to a file named mymod.ex. We can use it in multiple ways:

  • launch iex and evaluate the code in the spawned shell session:

    $ iex mymod.ex
    
    iex> M.hi "Alex"
    Hello, Alex
    :ok
    
  • evaluate it before running some other code. For example, to evaluate a single expression on the command line, use elixir -e <expr>. You can "require" (basically, evaluate and load) one or more files before it:

    $ elixir -r mymod.ex -e 'M.hi "Alex"'
    Hello, Alex
    
  • compile it and let the code loading facility of the VM find it

    $ elixirc mymod.ex
    $ iex
    iex> M.hi "Alex"
    Hello, Alex
    :ok
    

In that last example we compiled the module which produced a file named Elixir.M.beam in the current directory. When you then run iex in the same directory, the module will be loaded the first time a function from it is called. You could also use other ways to evaluate code, like elixir -e 'M.hi "..."'. As long as the .beam file can be found by the code loader, the module will be loaded and the appropriate function in it will be executed.


However, this was all about trying to play with some code examples. When you are ready to build a project in Elixir, you will need to use mix. The workflow with mix is more or less as follows:

$ mix new myproj
* creating README.md
* creating .gitignore
* creating mix.exs
[...]

$ cd myproj

# 'mix new' has generated a dummy test for you
# see test/myproj_test.exs
$ mix test

Add new modules in the lib/ directory. It is customary to prefix all module names with your project name. So if you take the M module we defined above and put it into the file lib/m.ex, it'll look like this:

 defmodule Myproj.M do
   def hi(name) do
     IO.puts "Hello, #{name}"
   end
 end

Now you can start a shell with the Mix project loaded in it.

 $ iex -S mix

Running the above will compile all your source file and will put them under the _build directory. Mix will also set up the code path for you so that the code loader can locate .beam files in that directory.

Evaluating expressions in the context of a mix project looks like this:

$ mix run -e 'Myproj.M.hi "..."'

Again, no need to compile anything. Most mix tasks will recompile any changed files, so you can safely assume that any modules you have defined are available when you call functions from them.

Run mix help to see all available tasks and mix help <task> to get a detailed description of a particular task.