Skip to content

Instantly share code, notes, and snippets.

@mrroot5
Last active January 21, 2022 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrroot5/d8e51baf6b0da660c0a7936f9f38c5de to your computer and use it in GitHub Desktop.
Save mrroot5/d8e51baf6b0da660c0a7936f9f38c5de to your computer and use it in GitHub Desktop.
Elixir cheatsheet. Keywords: elixir, how to, elixir how to, cheatsheet, elixir cheatsheet

Intro

Elixir cheat sheet with a question and explanation.

How to print a list of integers avoiding ASCII conversion?

numbers_list = [104, 101, 108, 108, 111]
# Output:hello

IO.inspect numbers_list, charlists: :as_lists
# Output:
# [104, 101, 108, 108, 111]
# 'hello'

How to compare: and, or, not vs &&, ||, !

  • We use and, or and not to compare booleans. If you don't use a boolean a BadBooleanError will be raised.
iex> 1 and true
** (BadBooleanError) expected a boolean on left-side of "and", got: 1
  • We use &&, || and ! to compare any type. Important all type will be evaluated to true except nil and false.
# or
iex> false || 11
11

# and
iex> nil && 13
nil

# not
iex> !1
false
iex> !nil
true

How to compare: ==, !=, ===, !==, <=, >=, < and >

Comparison operators works as expected but in Elixir, we can compare two different data types:

iex> 1 < :atom
true
number < atom < reference < function < port < pid < tuple < map < list < bitstring

Patter matching similar to destructuring in other languages

Same type required

  • This is ok:
{a, b, c} = {:hello, "world", 42}
  • This will fail:
iex> {a, b, c} = [:hello, "world", 42]
** (MatchError) no match of right hand side value: [:hello, "world", 42]

Same size is required

  • This will fail:
{a, b, c} = {:hello, "world"}
** (MatchError) no match of right hand side value: {:hello, "world"}

Match specific value

  • Match a specific value and get the next as variable:
iex> {:ok, result} = {:ok, 13}
{:ok, 13} # Change :ok by your own value to try it
iex> result
13

In this example we match the atom :ok and get the next value of this tuple.

  • Match head and tail of a list:
iex> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex> head
1
iex> tail
[2, 3]

If list is empty we will get a MatchError.

  • Match only head of a list:
iex> [head | _] = [1, 2, 3]
[1, 2, 3]
iex> head
1

If list is empty we will get a MatchError. The variable _ is special in that it can never be read from:

iex> 
** (CompileError) iex:1: invalid use of _. "_" represents a value to be ignored in a pattern and cannot be used in expressions

Scope

If any variable is declared or changed inside if, case, and similar constructs, the declaration and change will only be visible inside the construct.

iex> x = 1
1
iex> if true do
...>   x = x + 1
...> end
2
iex> x
1

How to change a variable inside an if, case, etc.?

Check if a list contains a map

iex> mixed_content = [1, "foo", 3.0, %{foo: "bar"}]
1. [1, "foo", 3.0, %{foo: "bar"}]
iex> list_has_map = &(nil != Enum.find(&1, fn element -> is_map(element) end))
iex> list_has_map.(mixed_content)
true

Garbage collector

Atoms

Atoms are never collected so we should never convert user input to atoms because the user can inject enough different inputs to exhaust our system memory.

Phoenix

Use controller variables in template

  • Sample controller with a login view:
def login(conn, _params) do
  render(conn, "login.html",
    body_class: "my_custom_class"
  )
end
  • Sample body tag on root.html.heex:
<body class={assigns[:body_class] || ""}>

Explanation: in controller login we set an assign with body_class as a key (atom) and the value "my_custom_class". Then we use body_class with assigns[:body_class] and use "" as default

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment