Elixir Data Types (Part 2)

May 23rd, 2021
#Backend #Elixir #Introduction to Elixir #Quickstart #Series

In this post, we will look at Elixir data types: integer, float, booleans, string, lists, maps, tuples... I will try to make this article concise as possible.

Getting Started

This post expects that you fiddle with the language by writing code to try out any of the given examples. Typing out these examples yourself helps improve memory muscles. So you are expected to have Elixir installed on your machine and you can run the interactive shell.

Visit the installation page once you are done run elixir --version to make sure that your installation matches the below requirements:

  • Elixir 1.5.0 onwards
  • Erlang/OTP 19 onwards

Interactive Shell

When the installation is completed, you will have 3 binaries added to your PATH: iex, elixir, and elixirc. You should start the interactive shell by running iex (iex.bat on Windows Command Prompt or PowerShell) to startup Elixir in interactive mode. We can type an expression and get a result in this shell.

Let's warm-up by running the below expression:

Erlang/OTP 23.0 [64-bit] [smp:2:2] [...]

Interactive Elixir (1.11.4) - press Ctrl+C to exit

iex(2)> "hello" <> " world"
"hello world"

Now we can push forward because we've been able to ascertain that Elixir is installed and we can access the interactive shell.

Numbers

Elixir sees the integer and float as two distinct types even though they fall under the Number category.

iex> 1		# integer
iex> 0x1F	# integer
iex> 1.0	# float

Open up the iex if you haven't, and let's see the possible arithmetic operations we can perform using numbers — you can perform more complex operations than the examples show.

iex> 1 + 1
2
iex> 20 - 5
15
iex> 8 / 4
2.0
iex> 7 * 7
49
iex> 0b1010 # binary
10
iex> 0o777 # octal
511
iex> 0x1F # hexadecimal
31

As seen in the example above you will notice that the expression 8 / 4 returns 2.0 which is a float value. This is expected in Elixir because the / operator always returns a float even the numbers used are integers like we have above. So if you to perform some integer operations without losing to the float you should invoke the div and rem functions for division and remainder of division respectively — I know we've not talked about functions yet but be rest assured we will.

iex> div(8, 4)
2
iex> rem(9, 2)
1

Floats require a dot followed by a digit, and you can also use e to denote scientific notations.

iex> 1.0
1.0
iex> round(3.9) # the round function rounds up to nearest integer
4
iex> trunc(2.56) # the trun function gets the integer part of a float
2
iex> 1.0e-10
1.0e-10

Booleans

Elixir supports true and false as boolean values, this means that you can't use any other datatype to depict a boolean value.

iex> true
true
iex> false
false
iex> is_boolean(true)
true
iex> is_boolean(0)
false

Note that Elixir provides a bunch of predicate functions to use to check for a value type: is_boolean, is_number, is_integer, is_float...

Atoms

An atom is a constant whose value is its name. Some other languages call these symbols. - Elixir Docs

iex> :ok
:ok
iex> :error
:error
iex> :sent
:sent

One thing to keep at the back of your mind is that Atoms are mostly used to depict the state of an operation so don't be surprised when you see it thrown around in an Elixir project 😄

NOTE: The booleans are also atoms, you can confirm this by running the predicate function is_atom(true) or is_atom(false).

Strings

A string is a sequence of characters delimited by double quotes and they are encoded in UTF-8 and interpolation of variables is allowed in a string.

iex> "Welcome to Elixir"
"Welcome to Elixir"
iex> name = "Reader"
iex> "I look forward to you loving Elixir, #{name}."
"I look forward to you loving Elixir, Reader"
iex> "hellõ wørld"
"hellõ wørld"

And you can test if a value is a string using is_binary predicate function while using String.length and byte_size to get the length of a string and the number of bytes in a string.

iex> is_binary(true)
false
iex> is_binary("am I a string?")
true
iex> String.length("beginner")
8
iex> byte_size("Elixir")
6

Lists

As the name implies, Lists are used to hold a collection of items, any data type. The square brackets [ and ] are used to denote a list.

iex> list = [1, 2, 3, "elixir", true]
[1, 2, 3, "elixir", true]
iex> length(list)
5

And note that a List in Elixir is a linked list unlike other programming languages

iex> list = ["Charles", "Turing", "José"]
["Charles", "Turing", "José"]
iex> hd(list)
"Charles"
iex> tl(list)
["Turing", "José"]

You should the hd and tl to grab the head and tail of a list respectively. And there is the ++ and -- operator to append and subtract from a list. See the example below:

iex> [1, 2, 3, 4] ++ [5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8]
iex> [1, 2, 3, 4] -- [3, 2]
[1, 4]

Maps

Map is basically a key-value store. It's created using the %{}:

iex> lang = %{name: "Elixir", paradigm: "Functional", creator: "José Valim"}
%{name: "Elixir", paradigm: "Functional", creator: "José Valim"}
iex> lang[:name]
"Elixir"
iex> lang[:paradigm]
"Functional"
iex> lang.creator
"José Valim"

Below are characteristics of a map:

  • The map allows any value as its keys meaning that you can have a string, atom, number...
  • The keys are not ordered

Tuples

Like lists, tuples that can hold any value are depicted using the { and }.

iex> {:ok, "hello"}
{:ok, "hello"}
iex> tuple_size({:ok, "hello"})
2

You should use the elem and put_elem to access and modify a tuple:

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

One very important use of tuple is to use them to return extra information from a function:

iex> Map.fetch(%{a: 1}, :a)
{:ok, 1}
iex> Map.fetch(%{a: 1}, :b)
:error

Keyword Lists

In Elixir, when a list contains 2-item tuples as values and the first value of the tuple is an atom, we call it a keyword list. A keyword list is a list, so every operator that can be used on a list can be used in the same manner:

iex> [{:otp_app, :hello_app}, {:deps, [...]}]
[otp_app: :hello_app, deps: [...]]
iex> [{:a, 1}, {:b, 2}]
[a: 1, b: 2]

And Elixir has another syntax to define such list:

iex> [otp_app: :hello_app, deps: [...]]
[otp_app: :hello_app, deps: [...]]

It's very common to find the keyword list in other functional languages. Below are characteristics of a keyword list:

  • Keys must be atoms.
  • Keys are ordered, as specified by the developer.
  • Keys can be given more than once.

Closing

Remember that Elixir upholds the Immutability mantra of a functional language meaning that modifications made on a value return another copy of the value with the modifications without modifying the actual value in place.

Going forward, we will be visiting the Functions, Modules, and beautiful features that allow you concise and declarative code.

Introduction to Elixir (Part 1)
previous

Made with 💙 © 2020 Atanda Rasheed