Elixir Cheatsheet for Node.js Developers

Table of Contents

Hello World

Elixir

# hello.exs
defmodule Greeter do
  def greet(name) do
    message = "Hello, " <> name <> "!"
    IO.puts message
  end
end

Greeter.greet("world")

JavaScript

// hello.js
console.log("Hello, world!");

    
    
    
    
    
    

Variables

Elixir

x = 1

JavaScript

let x = 1;

Nota bene: Elixir variables are immutable. Once assigned, they cannot be changed only reassigned.

N.B.2: the elixir = operator is used for assignment, but it is the match operator. Check pattern matching docs for a deep dive or take a quick look you sexy beast.

Types

Primitive Types

1          # integer
0x1F       # integer -> no JS equivalent
1.0        # float
true       # boolean
:atom      # atom / symbol -> no JS equivalent
"elixir"   # string
[1, 2, 3]  # list
{1, 2, 3}  # tuple
%{a: 1}    # map -> Object
%Person{name: "John Doe", age: 30}  # struct -> Interface
def function() do ... end  # function

Strings

Elixir

"elixir"  # "elixir"
"elixir" <> " " <> "rocks"  # "elixir rocks"
~s(elixir \x26 #{"inter" <> "polation"}) # "elixir & interpolation"
~S(elixir \x26 #{"inter" <> "polation"}) # "elixir \\x26 #{"inter" <> "polation"}"

JavaScript

"JavaScript"  // string
"JavaScript" + " " + "rocks"  // "JavaScript rocks"
`JavaScript ${"inter" + "polation"}`  // "JavaScript interpolation"
    

Maps

Elixir

address = %{city: "London", country: "UK"}
address[:city]  # "London"
address.country  # "UK"

JavaScript

let address = {city: "London", country: "UK"};
address.city  // "London"
address["country"]  // "UK"

Lists

Elixir

[1, 2, 3]  # list
[1 | [2 | [3 | []]]]  # list
[1, 2, 3] ++ [4, 5, 6]  # [1, 2, 3, 4, 5, 6]
[1, 2, 3] -- [2]  # [1, 3]
[1, 2, 3] -- [2, 3]  # [1]
[1, 2, 3] -- [2, 3, 4]  # [1]

JavaScript

[1, 2, 3]  // list
[1, ...[2, ...[3, ...[]]]]  // list
[1, 2, 3].concat([4, 5, 6])  // [1, 2, 3, 4, 5, 6]
[1, 2, 3].filter(x => x !== 2)  // [1, 3]
[1, 2, 3].filter(x => x !== 2 && x !== 3)  // [1]
[1, 2, 3].filter(x => x !== 2 && x !== 3 && x !== 4)  // [1]

Nota bene: Elixir stores lists and tuples very differently in memory. If you want performant code: look it up honey.

head and tail

The [head | tail] syntax provides functionality similar to destructuring lists in JavaScript.

Elixir

[head | tail] = [1, 2, 3]
head  # 1
tail  # [2, 3]
[first_element | _] = ['banana', 'apple', 'orange']
first_element  # 'banana'
[_first | rest] = ['brick', 'mortar', 'stone'] # _first is unused variable
rest  # ['mortar', 'stone']

JavaScript

let [head, ...tail] = [1, 2, 3];
head  // 1
tail  // [2, 3]



    

Nota bene[head | tail] requires a variable name for ‘head’ and ‘tail’. In elixir ’_’ is a valid variable name and it is used to signify ignored/unused values. It is either the name of a variable [first_element | _] or a prefix for a variable name [_first | rest].

Touples

Elixir

{1, 2, 3}  # tuple
{1, 2, 3} ++ {4, 5, 6}  # {1, 2, 3, 4, 5, 6}
{1, 2, 3} -- {2}  # {1, 3}
{1, 2, 3} -- {2, 3}  # {1}
{1, 2, 3} -- {2, 3, 4}  # {1}
    

JavaScript

[1, 2, 3]  // tuple
[1, ...[2, ...[3, ...[]]]]  // tuple
[1, 2, 3].concat([4, 5, 6])  // [1, 2, 3, 4, 5, 6]
[1, 2, 3].filter(x => x !== 2)  // [1, 3]
[1, 2, 3].filter(x => x !== 2 && x !== 3)  // [1]
[1, 2, 3].filter(x => x !== 2 && x !== 3 && x !== 4)  // [1]

Functions

Elixir

def greet(name) do # do/end syntax
  "Hello, " <> name <> "!"
end
greet("world")  # "Hello, world!"

def greet2(name), do: "Hello, " <> name <> "!"  # keyword syntax
greet2("world")  # "Hello, world!"

JavaScript

function greet(name) {
  return "Hello, " + name + "!";
}
greet("world")  // "Hello, world!"
    
    
    

Anonymous Functions

Elixir

fn (name) -> "Hello, " <> name <> "!" end # arrow syntax
fn (name), do: "Hello, " <> name <> "!"  # keyword syntax
fn (name) do
  "Hello, " <> name <> "!"
end
my_greet = fn (name) -> "Hello, " <> name <> "!" end # assign anonymous function to variable
my_greet.("world")  # "Hello, world!"

JavaScript

let myGreet = (name => "Hello, " + name + "!")
myGreet("world")  // "Hello, world!"
    
        
        
        
        

Sigils

~r{regexp}  # regular expression
~r"hello"
iex> ~s(string with escape codes \x26 stuff)  # string with codes
"string with escape codes & stuff"
iex> ~S(string without escape codes \x26 stuff)  # string without codes
"string without escape codes \\x26 stuff"
~c{charlist}  # charlist
~w{words}  # word list

Control Flow

if/unless

Elixir

if true do
  "true"
else
  "false"
end
unless true do
  "You may never see me"
end

JavaScript

if (true) {
  "true";
} else {
  "false";
}
if (!true) {
  "You may never see me";
}

Since in Elixir everything is a function if/unless can be used as a JS ternary operator.

Elixir

lunch = if hungry do
  "pizza"
else
  "salad"
end

dress = unless cold, do: "shorts", else: "pants"

JavaScript

let lunch = hungry ? "pizza" : "salad";
let dress = !cold ? "shorts" : "pants";
    
    
    
    
    

switch/case

Elixir

case {1, 2, 3} do
  {4, 5, 6} -> "nope"
  {1, 2, 3} -> "yep"
end

    

JavaScript

switch ([1, 2, 3]) {
  case [4, 5, 6]:
    "nope";
  case [1, 2, 3]:
    "yep";
}

cond

Elixir

cond do
  2 + 2 == 5 ->
    "This will never be true"
  2 * 2 == 3 ->
    "Nor this"
  1 + 1 == 2 ->
    "But this will"
end

JavaScript

if (2 + 2 === 5) {
  "This will never be true";
} else if (2 * 2 === 3) {
  "Nor this";
} else if (1 + 1 === 2) {
  "But this will";
}
    

Pattern Matching

keep scrolling for black magic [1]

Modules

Elixir

require Redux   # compiles a module
import Redux    # compiles, and you can use without the `Redux.` prefix // adds functions to the current scope

use Redux       # compiles, and runs Redux.__using__/1
use Redux, async: true

import Redux, only: [duplicate: 2]
import Redux, only: :functions
import Redux, only: :macros

import Foo.{Bar, Baz}

defmodule Foo do    # defines a module
  def Bar, do: "Bar"
end

JavaScript

const Redux = require('redux');  // compiles a module
import Redux from 'redux';  // compiles, and you can use without the `Redux.` prefix // adds functions to the current scope
import { Bar, Baz } from Foo;
    
    
    
    
    
    
    
    
    
    
    
    

Structs

defmodule Person do
  defstruct name: "John Doe", age: 30  # defines a Person struct with default values
end
Footnotes
1. If you are an exorcist, we are not responsible for the possible flashing lights, hellfire, witchcraft, or any other supernatural phenomena that may occur while reading this section.