Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Data Types

class1/data_types.livemd

Data Types

Numbers

Elixir have 2 types to work with numbers: integers and floats.
Notes: Integers automatically expand memory they take to accomodate values (e.g. from int’s to bigInt’s)

# Integer examples

1
+2
-3
1_000_000_000
# binary notation
0b1010
# octal notation
0o777
# hexadecimal notation
0x1F

12.345
-2.71
3.14e-10
123_456.789_1011e23

Arithmetic operations work as in most programming languages (+, -, *, /, div/2, rem/2)

1 + 2
3 - 4
5 * 6
2 * 1.3
8 / 2
div(8, 2)
rem(8, 3)

Atoms

An atom is a constant whose value is its own name. Atoms must be composed of Unicode characters such as letters, numbers, underscore, and @. If the keyword has a character that does not belong to the category above, such as spaces, you can wrap it in quotes.

:apple
:a_pple
:apple_2
:localhost@me
:"atom with spaces"
:apple == :orange
# :apple == :apple
# :apple == :Apple
# is_atom(:apple)

Booleans

Booleans are in fact just atoms :true and :false. In Elixir boolean logic there is a concept of truthly values. There is no separare value for nil therefore atom :nil is used. You can type nil for simplicity sake. Boolean operators && and || consider nil to be the same as false and anything else is consifered to be true. Operator ! negates the truthly values.

true
# true == :true
# true === :true
# !true
# ! :true
nil
# ! nil
# ! :whatever
# nil || :something
# true && :something

Chars

Chars are stored as their unicode values (integers).

?a
IO.inspect(?a)
is_integer(?a)
?a == 97
?a - ?b

String

String are delimited by double quotes, and are encoded in UTF-8. They also support string interpolation, escape sequences. Internally represented by contiguous sequences of bytes known as binaries.

a = :world
"hello #{a}"
IO.puts("hello\nworld")
is_binary("hello")
"hello" <> " " <> "world"

Lists

Elixir uses square brackets to specify a list of values. Values can be of any type, and lists can be concatenated or subtracted using the ++ and -- operators. You can create a list by putting all the values in the brackets or use a recursive definition [head | tail] where tail is also a list.

[]
# [1]
# [:asdf, 1, "apple", true]
[1, 2, 3] ++ [4, 5, 6]
# [1, 1, 2, 5, 3, 4] -- [4, 1]
[1, 2, 3]
# [1 | [2, 3]]
# [1, 2, 3] == [1 | [2, 3]]
# [1 | [2 | [3]]]
# [1 | [2 | [3 | []]]]
# built-in functions hd/1 tl/1
hd([:a, :b, :c])
# tl([:a, :b, :c])

Tuples

Group of elements with constant size. Fast access time than lists

tuple = {:ok, "hello"}
# tuple_size({:ok, "hello"})
# elem(tuple, 1)
# put_elem(tuple, 1, "world")
# tuple

Keyword lists

List consisting of 2-item tuples where the first element is an atom and the second element can be any value. Keyword list have 3 special characterisitcs:

  • keys must be atoms
  • keys are ordered
  • keys can be given more then once
{:trim, true}
# [{:trim, true}] == [trim: true]
# [a: 1, b: 2] == [b: 2, a: 1]
# usual list operations are available
# list = [a: 1, b: 2]
# list ++ [c: 3]

Maps

Maps are created using %{} syntax, classic key-value store.

%{}
# Map.new()

# computer = %{
#   :type => :pc,
#   "graphics card" => ["GTX", 760],
#   {:processor, "intel"} => [{8, :cores}, {:type, :x86}]
# }

# computer[:type]
# computer[{:processor, "intel"}]
# computer["graphics card"]
# computer[:not_exixsting_key]
# Map.get(computer, :not_existing_key)
# Map.get(computer, :not_existing_key, "default_value")

# computer.type
# # computer.not_exixsting_key
# # computer."graphics card"

# laptop = %{computer | :type => :laptop}
# # laptop = %{computer | :sound => {:serround, 5.1}}
# laptop = Map.put(computer, :sound, {:serround, 5.1})

# tablet = %{:type => %{device_type: :tablet, os: :android}}

# tablet.type.os
# tablet[:type].os
# tablet.type[:os]
# tablet[:type][:os]

Structs

Structs are extensions built on top of maps that provide compile-time checks and default values.

defmodule Device do
  defstruct device_type: nil,
            os: :linux,
            processor: nil
end
pc = %Device{
  device_type: :pc
}

# pc.os

# tablet = %Device{
#   device_type: :tablet,
#   processor: {:intel, :x86},
#   os: :android
# }