Elixir 4. Type System, Numbers, Atoms, Boolean, Nil, Tuples, List, Immutability
Elixir Type System
Elixir uses Erlang Type System, so integration with Erlang libraries is super simple.
Numbers
Number can be Integer
or Float
, there is no size limit for Integer
they can be arbitrary larger, but Float
can only be 32
or 64
bit depending on the arch of system.
- We use
10_000_000
(underscore) to separate numbers. /
division operator will always givefloat
value
iex(2)> 5 / 5
1.0
iex(3)> 10 / 3
3.3333333333333335
iex(4)> 24 / 2
12.0
iex(5)>
Kernel.div(a, b)
(or justdiv(a, b)
) is for normal divisionKernel.rem(a, b)
(or justrem(a, b)
) is or remainder ,%
operator
Atoms
An Atoms
is a symbol
or enum
which has a value of its name
iex(6)> :kunalsin9h
:kunalsin9h
iex(7)>
Here :kunalsin9h
is a Symbol or an enum, (means now it have become a type)
- An
atom
can have spaces
iex(1)> :"i am an atom"
:"i am an atom"
iex(2)>
Boolean
There is not boolean
type in the Elixir, we use :true
and :false
atoms, so this is such a common pattern, we can omit the colon and just use true
and false
, but remember they are atoms.
iex(2)> true
true
iex(3)> :true
true
iex(4)> false
false
iex(5)> :false
false
iex(6)> :true == true
true
iex(7)> :false == false
true
iex(8)> :true and false
false
iex(9)> :false and true
false
iex(10)> true and true
true
iex(11)> true or false
true
iex(12)> false or true
true
iex(13)>
Nil
nil
is similar to null
in other languages, it is also an atom, :nil
iex(16)> :nil == nil
true
iex(17)> nil
nil
iex(18)> :nil
nil
iex(19)>
The atom
nil
andfalse
is considered asfalsy
values , expect these everything istruthy
value.
We can also use short circuiting using
and
&&
or
||
not
!
Tuples
Tuples are group of fixed number of elements. we user {}
this to make a tuple
iex(25)> user = {"KunalSin9h", 21}
{"KunalSin9h", 21}
iex(26)> user
{"KunalSin9h", 21}
iex(27)>
- Get the element of the tuple, zero based indexing
iex(26)> user
{"KunalSin9h", 21}
iex(27)> elem(user, 1)
21
iex(28)> elem(user, 0)
"KunalSin9h"
iex(29)>
elem
is function inside the Kernel
module.
- Replace the tuple element,
put_elem
is also a function inKernel
module, it takes (tuple
,index
,element_to_put
)
iex(29)> put_elem(user, 1, 1000)
{"KunalSin9h", 1000}
iex(30)>
But the user
tuple is still
iex(29)> put_elem(user, 1, 1000)
{"KunalSin9h", 1000}
iex(30)> user
{"KunalSin9h", 21}
iex(31)>
This is because, in Elixir every data is immutable
, we can't update / change a variable, so we need to store it in new variable, or rebound
(reassign
) to the same variable.
Tuples are most appropriate for grouping a small, fixed number of elements together. When you need a dynamically sized collection, you can use lists.
List
List is dynamic, variable_size, we create list by []
List operation: List @ Hex Doc
iex(38)> prime_number = [2, 3, 6, 7, 11]
[2, 3, 6, 7, 11]
iex(39)> prime_number
[2, 3, 6, 7, 11]
iex(40)> length(prime_number)
5
iex(41)>
List is implemented using Linked List
so every operation is O(n)
.
- length(list)
- Enum.at(list, index)
- List.replace_at(list, idx, val)
- List.insert_at(list, idx, val)
- List.insert_at(list, -1, val)
Append
iex(42)> Enum.at(prime_number, 3)
7
iex(43)> 11 in prime_number
true
iex(44)> new_prime_number = List.replace_at(prime_number, 0, 13)
[13, 3, 6, 7, 11]
iex(45)> new_prime_number = List.insert_at(prime_number, 2, 17)
[2, 3, 17, 6, 7, 11]
iex(46)> new_prime_number = List.insert_at(prime_number, -1, 111)
[2, 3, 6, 7, 11, 111]
- List Concatenation, the
++
op
iex(1)> [1, 2, 3, 4] ++ [6, 7, 8, 9]
[1, 2, 3, 4, 6, 7, 8, 9]
iex(2)>
- Recursive List
List is essentially a (head
, tail
) pair, where head is the first element of the list and tail “points”to the (head, tail) pair of the remaining elements. []
indicate that tail
is pointing to nowhere.
iex(3)> [1 | [2 | [ 3 | [4 | [5 | [] ] ]]]]
[1, 2, 3, 4, 5]
iex(4)>
Internally list
are recursive structure of (head
, tail
) pair. So, we can get head
and tail
from the list, using hd
and tl
.
iex(4)> l = [1 | [2 | [ 3 | [4 | [5 | [] ] ]]]]
[1, 2, 3, 4, 5]
iex(5)> hd l
1
iex(6)> tl l
[2, 3, 4, 5]
iex(7)> hd(l)
1
iex(8)> tl(l)
[2, 3, 4, 5]
iex(9)>
These op are just O(1)
because they amount to reading one or the other value from the (head, tail) pair.
Now, it is simple and efficient to push element on top of list (push- front
)
iex(9)> a = [1, 2, 3]
[1, 2, 3]
iex(10)> hd(a)
1
iex(11)> tl(a)
[2, 3]
iex(12)> a = [4 | a]
[4, 1, 2, 3]
iex(13)>
Immutability
Elixir Data Can't Be Mutated
Because variables reference the data, i can case that many other variables are referencing the same variable, and if we update one of the variable, which in turn update the memory location, this leads to data corruption for other variables.
So what Elixir does is, it makes a new memory block, put the data and reference the variable.
An data which are stale in the process will be garbage collected.