Skip to content

Instantly share code, notes, and snippets.

@anandgeorge
Created July 22, 2021 15:23
Show Gist options
  • Save anandgeorge/ba6f9ed03c9a6fba532dbea68d612f6e to your computer and use it in GitHub Desktop.
Save anandgeorge/ba6f9ed03c9a6fba532dbea68d612f6e to your computer and use it in GitHub Desktop.
Elixir Data Types, Maps, Lists, Tuples and Pattern Matching TIps
Access help functions for a module using the h command; so
h String
will give you help related to the String function
#### Data types
iex> 2 # integer
iex> 2.0 # floating point
iex> false # boolean
iex> 1..4 # range
iex> ~r/hello/ # regular expression
iex> :hello # atom
iex> "world" # string
iex> 'world' # charlist
iex> #Port<0.1306> # port
iex> #PID<0.123.0> # pid
You should always enclose strings within double quotes.
If you use single quotes, that creates a charlist, which is a different type.
Variable names cannot begin with a captial letter
iex(4)> Radius = 2
** (MatchError) no match of right hand side value: 2
#### Modules
Module names use CamelCase starting with a capital letter. Function names use snake_case.
defmodule Calculator.Area is a perfectly valid module name without defining Calculator separately
Modules can be nested and referred using the dot notation
defmodule Calculator do
defmodule Area do
def square(a) do
a * a
end
end
end
The function can be referred to by calling Calculator.Area.square(5)
#### Import modules
Modules can be imported and the functions therein can be called directly
import Calculator.Area then we can call
square(5) directly
However importing Calculator does not allow you to call
Area.square(5)
Limiting the import
defmodule Rectangle do
def area(a) do
a * a
end
def area(a, b) do
a * b
end
end
import Rectangle, only: [area: 2] only gives access to specific functions
area(4) will throw an error
area(4, 5) works
Alias on the other hand sets the alias of the module. So functions have to be still called in the context of the submodule.
They cannot be called directly as in the case of import
alias Calculator.Area, as: Area or
alias Calculator.Area, as: A
Atoms start with a :
Atoms are usually written in snake_case
Strings
first_name = "Anand"
"Anand"
last_name = "George"
"George"
name = first_name <> " " <> last_name # String concatenation
"Anand George"
greeting = "Hello #{first_name}!" # Replacing variables in a string
"Hello Anand!"
Pipe operator
String.reverse("house") \ # the backslash is used to tell the interpreter to continue on the next line
|> String.capitalize()
#### Lists
Lists store multiple values, and they can contain different types. A list is enclosed in brackets []
A list is a linked list so it stores values in sequence.
[1, 2, 3, 4]
[5 ,4, true, false]
Adding and subtracting lists uses the ++ and -- operator
[1, 2] ++ [2, 4]
[1, "a", 2, false, true] -- ["a", 2]
hd returns the first element of the list and tl returns the rest of the list
shopping_list = ["apple", "orange", "banana", "pineapple"]
hd(shopping_list)
"apple"
tl(shopping_list)
["orange", "banana", "pineapple"]
hd([]) and tl([]) returns an error
length returns length of the list
length([1, 2]) returns 2
numbers = [1,5,3,7,2,3,9,5,3]
Enum.max(numbers)
Enum.sort(numbers)
Enum.join(["nothing", "like", "the", "sun"], " ")
#### Tuples
Tuples are arrays that can hold multiple elements. Tuples can be accessed by index.
They are meant to hold a fixed number of related elements.
{1, 2, 3}
{:ok, "test"}
result = {:ok, "Lorem ipsum"}
elem(result, 1)
"Lorem ipsum"
b = Tuple.append(results, "Test")
c = Tuple.delete_at(b, 1)
d = Tuple.insert_at(b, 1, "ipsum")
new_list = Tuple.to_list(d)
tuple_size(d)
#### Keyword lists
Keyword lists are key-value data structures, in which keys are atoms and keys can appear more than once.
list1 = [ name: "Miguel Palhas", email: "miguel@example.com" ]
As it turns out, this is just syntactic sugar for a list, where each value is a 2-element tuple. It is equivalent to:
list2 = [
{ :name, "Miguel Palhas"},
{ :email, "miguel@example.com" }
]
user = [{:name, "joe"}, {:age, 23}]
or
anuser = [name: "joe", age: 23]
user[:name]
Keyword.get(user, :age)
23
Keyword.delete([length: 78, width: 104], :length)
[width: 104]
#### Maps
Maps are a real key-value store. A key has to be unique within a map.
Maps are good for passing associative data around, and pretty much everything else that is bigger than tuple size.
iex> %{"greeting" => "hello", "noun" => "world"}
Using atoms as keys
product_prices = %{apple: 0.5, orange: 0.7}
%{apple: 0.5, orange: 0.7}
product_prices.apple
0.5
product_prices = %{apple: 0.5, orange: 0.7, coconut: 1}
%{apple: 0.5, coconut: 1, orange: 0.7}
Map.to_list(product_prices)
[apple: 0.5, coconut: 1, orange: 0.7]
Map.values(product_prices)
[0.5, 1, 0.7]
Map.split(product_prices, [:orange, :apple])
{%{apple: 0.5, orange: 0.7}, %{coconut: 1}}
Map.delete(product_prices, :orange)
%{apple: 0.5, coconut: 1}
additional_prices = %{banana: 0.4, pineapple: 1.2}
%{banana: 0.4, pineapple: 1.2}
Map.merge(product_prices, additional_prices)
%{apple: 0.5, banana: 0.4, coconut: 1, orange: 0.7, pineapple: 1.2}
c = Map.put(product_prices, :potato, 0.2)
%{apple: 0.5, coconut: 1, orange: 0.7, potato: 0.2}
#### Structs
Structs are like enhanced maps. They permit only certain keys and those keys must be atoms.
They need to be defined in modules with reasonable default values. They're maps with rules.
A struct guarantees that only the defined fields are allowed.
iex> defmodule IceCream do
.... defstruct flavor: "", quantity: 0
.... end
iex> chocolate = %IceCream{flavor: "chocolate"}
iex> chocolate.flavor
iex> "chocolate"
#### Tuples vs Maps
In the Erlang VM, a tuple is always stored as a contiguous segment of memory –
the item at index n is stored at the memory address right after where n-1 ended.
As such, it's generally very bad form to do a lot of modifying of tuple content and structure,
as a good number of those operations will result in data being copied and collated at a new memory address.
Contrast this to lists, which the Erlang VM keeps track of by storing a reference to the previous
data point's address alongside the current data point. As such, not only is the length of a list dynamic,
its addresses within RAM are, too (and the newest data is, paradoxically, usually at the leftmost side of the list).
Matching a Map works a little bit different to matching a Tuple or List. You can match just against the values you are interested in.
#### Pattern Matching
{b, c} = {10, 15}
{10, 15}
b
10
#### Pattern matching Lists
shopping_list = ["apple", "orange", "banana", "pineapple"]
["apple", "orange", "banana", "pineapple"]
[head | tail] = shopping_list
["apple", "orange", "banana", "pineapple"]
head
"apple"
tail
["orange", "banana", "pineapple"]
[a | b] = shopping_list
["apple", "orange", "banana", "pineapple"]
a
"apple"
b
["orange", "banana", "pineapple"]
[a, b, c, d] = shopping_list
["apple", "orange", "banana", "pineapple"]
a
"apple"
c
"banana"
[a | _] = shopping_list # Wildcard pattern matching
["apple", "orange", "banana", "pineapple"]
a
"apple"
[first_product, second_product | tail] = shopping_list
["apple", "orange", "banana", "pineapple"]
second_product
"orange"
#### Pattern Matching Maps
product_prices = %{apple: 0.5, orange: 0.7, pineapple: 1}
%{apple: 0.5, orange: 0.7, pineapple: 1}
%{orange: price} = product_prices
%{apple: 0.5, orange: 0.7, pineapple: 1}
price
#### Pattern Matching Strings
user = "Anand George"
"Anand George"
"Anand " <> last_name = user
"Anand George"
last_name
"George"
#### Pattern Matching arguments
defmodule Area do
def circle(:exact, radius) do
3.14159265359 * radius * radius
end
def circle(:normal, radius) do
3.14 * radius * radius
end
def circle(radius) do
circle(:normal, radius)
end
end
#### Functions with guard clauses
defmodule Law do
def can_vote?(age) when is_integer(age) and age > 17 do
true
end
def can_vote?(age) when is_integer(age) do
false
end
def can_vote?(_age) do
raise ArgumentError, "age should be an integer"
end
end
#### Case with multiple conditions and patter matching
case result do
{:ok, file} -> "The file exists"
{:error, reason} -> "There was an error"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment