For the past year or so, I’ve been working on some interesting features in a bunch of different Ember apps at Wombat, but recently I’ve had the opportunity to learn a new language and help support our backend team on our Elixir API.

I’m no stranger to the backend as I’ve worked extensively in Ruby in the past plus a bit in C# and PHP, but have pretty much only been in the frontend recently. Elixir and Ember/Javascript are of course very different languages. Here are a few interesting things I noticed while learning Elixir plus some similarities that I’d like to share.

Unique

Pattern matching is one of the first things you learn in Elixir, but can be a bit challenging to comprehend initially. Once you get the hang of it though, it’s incredibly useful.

If you’re familiar with the = in just about any other language, you use it to set some type of variable to something else like x = 1, but in Elixir it’s known as the match operator. You can use it to do simple matching like x = 1, but where it’s really powerful is with more complex matching, allowing you to destructure more complex data structures.

A simple example from the Elixir docs is something like:

  iex> [a, b, c] = [1, 2, 3]
  [1, 2, 3]
  iex> a
  1
  iex> b
  2
  iex> c
  3

The example above is easy to understand, you are matching the left and the right and both sides have to have the same amount of variables to be a successful match otherwise it will error. A real world example where this becomes useful is that Elixir allows you to create functions with the same name but expects different parameters. We typically use this in our API where say we have a bunch of functions that all share the same name, but depending on the different arguments will do different operations.

  def hello(names, language_code \\ "en")
  def hello(names, language_code) when is_list(names) do
    names
    |> Enum.join(", ")
    |> hello(language_code)
  end

  def hello(name, language_code) when is_binary(name) do
    phrase(language_code) <> name
  end

Basically by using pattern matching you could write code like the example above and instead of having a bunch of different nested conditionals, you have different functions that are all similar but handle each case and even sets defaults, which is what the \\ signifies.

One other way Elixir uses pattern matching is with control flow structures. Its case statement allows you to compare against different patterns until a match is found. This essentially does the same thing as if elsif else.. The last condition defined below, which we’re calling our blanket statement, will match if none of the previous conditions match, doing the same as an else.

  case do_something() do
    {:ok, thing}    -> operate(thing)
    {:error, error} -> report_error(error)
    _blanket        -> report_error(blanket)
  end

Similar

One of the more interesting topics I found in Elixir and where I’ve seen some similarities to Ember has been using tasks. Tasks basically allow you to write concurrent asynchronous code rather than having to write code that is sequential and has to wait for other parts of the code or processes to finish. In Elixir you can write Task.async, which when invoked will create a new process to run some function that will be linked and monitored by the caller and once this task finishes, a message is sent to the caller with the result.

  task = Task.async(fn -> do_some_work() end)
  res  = do_some_other_work()
  res + Task.await(task)

In Ember/JavaScript, this is very reminiscent of Promises, which are essentially the same thing. Promises are objects returned when running some functions or making some request that represents the eventual completion or failure of that async operation. You don’t have to wait for the Promise to resolve as you can help going on with your other operations then it will eventually get its message/result back whenever it completes. You can then chain on other operations with the .then() function that will run once the promise resolves.

  this.get('ajax').request(`/users`, {
    method: 'GET'
  }).then((resp) => {
    // do something with response
  }).catch((err) => {
    // handle error
  });

Aside from just basic JavaScript promises, an Ember addon we’ve been using in our Ember apps at Wombat called Ember Concurrency, is even more like Elixir’s tasks. Ember Concurrency even uses a Task syntax. Once difference from promises is that Ember Concurrency allows you to cancel the task, just as you can do with Elixir tasks by running Task.shutdown.

  init() {
    this._super(...arguments);
    this.get('myTask').perform();
  },
  
  myTask: task(function * () {
    this.set('status', `Thinking...`);
    let promise = timeout(1000).then(() => 123);
    let resolvedValue = yield promise;
    this.set('status', `The value is ${resolvedValue}`);
  }),

This was in no way an extensive look into the unique and similar features between Ember and Elixir, but hopefully you have a little bit better of an understanding of both and are inspired to dive into either as well.