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
- @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:
- 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.
- 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.
- 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.
- 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: