Misc Blog

Elixir for JavaScript Programmers

Elixir is awesome, but not many people seem to know about it. Time to change that. Javascript developers - come here to get your feet wet with Elixir!

Name
Matt
Twitter
@mplatts

1 year ago

Elixir for JavaScript Programmers

What is Elixir?

Elixir is a modern, functional programming language that runs on the Erlang virtual machine. It was designed to be easy to learn and to write concurrent, scalable, and fault-tolerant applications. One of the key features of Elixir is its focus on concurrency and distributed systems, which makes it an excellent choice for building applications that need to handle a large number of users or requests.

Elixir vs Javascript

It’s essential to note that comparing Elixir and JavaScript directly can be misleading since they are designed for different purposes and excel in different domains. However, there are certain areas where Elixir demonstrates advantages over JavaScript:

  1. Concurrency: Elixir can handle thousands or even millions of lightweight processes simultaneously, thanks to BEAM’s efficient scheduling. JavaScript, on the other hand, relies on asynchronous callbacks or promises and event-driven programming, which can make handling concurrency more challenging and less efficient.
  2. Fault Tolerance: Elixir, being built on the BEAM, inherits Erlang’s fault-tolerant features, which enable the creation of highly reliable systems. JavaScript wasn’t designed with fault tolerance in mind, so achieving a similar level of reliability can require implementing custom solutions and libraries.
  3. Distributed Systems: Elixir’s native support for distributed systems allows it to build scalable applications that can span across multiple nodes or machines. In contrast, JavaScript relies on third-party libraries and frameworks to achieve similar functionality, which may not offer the same level of efficiency or simplicity.
  4. Performance: Although JavaScript has made significant strides in performance with V8 and other modern engines, Elixir’s performance is generally more predictable and consistent due to its immutable data structures, lightweight processes, and BEAM’s optimized garbage collection.

Basic Types

Numbers

In Elixir, there are two types of numbers: integers and floats.

JavaScript:

let intNum = 42;
let floatNum = 42.0;

Elixir:

int_num = 42
float_num = 42.0

Booleans

JavaScript:

let isTrue = true;
let isFalse = false;

Elixir:

is_true = true
is_false = false

Atoms

Atoms in Elixir are constants with a name. They are similar to symbols in JavaScript.

JavaScript:

const symbol = Symbol("example");

Elixir:

:example

Strings

Strings in Elixir are UTF-8 encoded, just like in JavaScript.

JavaScript:

let str = "Hello, world!";

Elixir:

str = "Hello, world!"

Lists

In Elixir, lists are similar to arrays in JavaScript. However, Elixir lists are linked lists, which makes appending items to the front of the list more efficient.

JavaScript:

let array = [1, 2, 3];

Elixir:

list = [1, 2, 3]

Tuples

Tuples in Elixir are similar to arrays in JavaScript but are stored contiguously in memory. They are useful for grouping data and are accessed in constant time.

JavaScript:

let tuple = [1, "two", 3.0];

Elixir:

tuple = {1, "two", 3.0}

Control Structures

Conditionals

In Elixir, you can use if, else, and cond for conditional statements.

JavaScript:

if (x > 0) {
  console.log("Positive");
} else {
  console.log("Negative");
}

// Shorthand
let result = x > 0 ? true : false;

Elixir:

if x > 0 do
  IO.puts("Positive")
end

# Shorthand
result = if x > 10, do: true, else: false

Case

Javascript:

let fruit = "apple";

switch (fruit) {
  case "apple":
    console.log("It's an apple");
    break;
  case "banana":
    console.log("It's a banana");
    break;
  default:
    console.log("Unknown fruit");
}

Elixir:

fruit = "apple"

case fruit do
  "apple" ->
    IO.puts "It's an apple"
  "banana" ->
    IO.puts "It's a banana"
  _ ->
    IO.puts "Unknown fruit"
end

Loops

Javascript:

const numbers = [1, 2, 3, 4, 5];

for (let i = 0; i < numbers.length; i++) {
  console.log(numbers[i]);
}

Elixir:

numbers = [1, 2, 3, 4, 5]

Enum.each(numbers, fn number -> IO.puts(number) end)

While

Javascript

let i = 0;

while (i < 5) {
  console.log(i);
  i++;
}

In Elixir, everything is immutable, but you can use recursion to achieve a similar effect:

defmodule Loop do
  def print_until(limit, current \\ 0) do
    if current < limit do
      IO.puts(current)
      print_until(limit, current + 1)
    end
  end
end

Loop.print_until(5)

However, Elixir also offers the Stream module for creating lazy, composable enumerables, which can be more efficient in certain cases:

0..4
|> Stream.each(&IO.puts/1)
|> Stream.run()

Pattern Matching

JavaScript:

// Array destructuring
const [first, second, third] = [1, 2, 3];

// Object destructuring
const { name, age } = { name: "Alice", age: 30 };

Elixir:

# Tuple matching
{a, b, c} = {:ok, 42, "hello"}

# List destructuring
[h | t] = [1, 2, 3]

# Map matching
%{name: name, age: age} = %{name: "Alice", age: 30, job: "Engineer"}

# Function pattern matching
defmodule Geometry do
  def area({:rectangle, width, height}) do
    width * height
  end

  def area({:circle, radius}) do
    :math.pi() * radius * radius
  end
end

Geometry.area({:rectangle, 10, 5})
Geometry.area({:circle, 5})

Functions

Elixir is a functional language, so functions are first-class citizens.

Anonymous Functions

JavaScript:

const sum = (a, b) => a + b;
console.log(sum(1, 2)); // 3

Elixir:

sum = fn a, b -> a + b end
IO.puts(sum.(1, 2)) # 3

Named Functions

Named functions are defined inside modules.

JavaScript:

function multiply(a, b) {
  return a * b;
}

console.log(multiply(2, 3)); // 6

Elixir:

defmodule Math do
  def multiply(a, b) do
    a * b
  end
end

IO.puts(Math.multiply(2, 3)) # 6

Modules

Modules are used to group functions in Elixir.

JavaScript:

const math = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b,
};

console.log(math.add(1, 2)); // 3

Elixir:

defmodule Math do
  def add(a, b) do
    a + b
  end

  def subtract(a, b) do
    a - b
  end
end

IO.puts(Math.add(1, 2)) # 3

Concurrency

Elixir supports concurrency using lightweight processes and message passing.

JavaScript:

setTimeout(() => {
  console.log("Hello from the future!");
}, 1000);

Elixir:

Process.spawn(fn ->
  :timer.sleep(1000)
  IO.puts("Hello from the future!")
end)

Resources

Here are some helpful resources to continue learning Elixir:

The end

More posts