elixir, data types

Getting Started with Elixir - Data Types

Data types are the most basic building blocks of any language.  In order to become proficient at building Phoenix applications, it's important to understand how Elixir works. So let's get started with Data Types.  

We'll be using IEx to explore some of the data types, so ensure that you have Elixir installed correctly.

Elixir Series

Data Types

Elixir has some common data types and others which have unique characteristics.

Here's a list of the available data types:

Type Examples
Integer 34
Float 234.23
Boolean true / false
String "Elixir Phoenix"
Charlist 'Elixir Phoenix'
Atom :elixir_phoenix
List [32, false, :dog]
Tuple {32, false, :dog}
Map %{name: "Tom", city: "New York"}
Range 1..100

Integers & Floats

Like most languages, numbers are pretty straightforward in Elixir.  

When working with floats, anything between -1 and 1 must be start with a zero: 0.213, 0.54.

Also, the division operator / will always return a float.  Try it out in IEx:

iex(1)> 4 / 2
2.0

Booleans

Again, pretty straightforward, booleans simply represent either a true or false value:

iex(1)> 2 > 1
true

iex(2)> 2 < 1
false

Strings

In Elixir, strings are stored as UTF-8 encoded binaries where each character is stored as its Unicode bytes. They are only enclosed in double quotes: "a string".  Read more about Elixir Strings in the docs.

An important distinction about strings is that anything wrapped in single quotes is a charlist: 'a charlist' which we'll cover next.

Some examples of working with Strings:

iex(1)> string = "a string"
"a string"

iex(2)> is_binary(string)
true

iex(3)> string = string <> " made longer"
"a string made longer"

Notice that strings can be concatenated using <>.

Charlists

A charlist is a special kind of list of ASCII number values that represent each character rather than the characters themselves.

We can use i() to inspect a charlist in IEx:

iex(2)> i('dog')
Term
  'dog'
Data type
  List
Description
  This is a list of integers that is printed as a sequence of characters
  delimited by single quotes because all the integers in it represent printable
  ASCII characters. Conventionally, a list of Unicode code points is known as a
  charlist and a list of ASCII characters is a subset of it.
Raw representation
  [100, 111, 103]
Reference modules
  List
Implemented protocols
  Collectable, Enumerable, IEx.Info, Inspect, List.Chars, String.Chars

You can see that the Raw representation is a list of the number values for each character.

If you enter the raw list in IEx:

iex(6)> [100, 111, 103]
'dog'

You'll get the charlist value.

This is important to understand because if you need to return a list value with integers, Elixir can interpret it as the charlistvalue.  

For situations like these it's often more common to use a Tuple, which don't have the same issues as lists/charlists:

iex(7)> {100, 111, 103}
{100, 111, 103}

Atoms

Atoms are similar to symbols in other languages like Ruby: :atom.

They're constants and cannot change.  There really isn't much more to them.

You'll commonly see them used as return values to functions:

iex(1)> Enum.fetch([1,2,3], 1)
{:ok, 2}

Enum.fetch returns a tuple where :ok is an atom and 2 is the value in position 1 from the zero-based list.

Lists

Lists are similar to arrays in other languages and are "lists" of items that may or may not be similar types.  They are known as "linked lists" meaning each item in the list has an internal pointer to the next item in the list.

Read more about (linked) lists in the docs.

They can contain mixed types and even other lists:

iex(1)> list1 = [1,2,3]
[1, 2, 3]

iex(2)> list2 = [:atom, "string", list1]
[:atom, "string", [1, 2, 3]]

Lists can be concatenated and subtracted from:

iex(3)> [1,2] ++ [3,4]
[1, 2, 3, 4]

iex(4)> [1,2,3,4] -- [3,4]
[1, 2]

There is also a way to separate the head from the tail of a list where the head is the first item in the list, and the tail is everything after.  (Sometime known as the guillotine).

iex(1)> [head | tail] = ["some", "list", "of", "strings"]
["some", "list", "of", "strings"]

iex(2)> head
"some"

iex(3)> tail
["list", "of", "strings"]

There is also a hd/1 function that will return the head of a list.

iex(4)> hd(["some", "list", "of", "strings"])
"some"

Tuples

Although tuples appear similar to lists, they are constructed differently under the hood and used differently in Elixir.  

Here's a great explanation from the docs:

Tuples are not meant to be used as a “collection” type (which is also suggested by the absence of an implementation of the Enumerable protocol for tuples): they’re mostly meant to be used as a fixed-size container for multiple elements. For example, tuples are often used to have functions return “enriched” values: a common pattern is for functions to return {:ok, value} for successful cases and {:error, reason} for unsuccessful cases.

Again, the fetch function can help demonstrate how they're commonly used:

iex(1)> Enum.fetch([1,2,3], 1)
{:ok, 2}

They can also contain multiple data types:

iex(2)> {:atom, "string", ["list"]}
{:atom, "string", ["list"]}

Maps

Maps are key / value stores where each value is bound to a unique key.  Similar to Hash in Ruby or Dictionary in others.

iex(3)> %{id: 1, title: "A Thing"}
%{id: 1, title: "A Thing"}

Map.fetch can be used to fetch an items value by passing the key:

iex(1)> map = %{id: 1, title: "A Thing"}
%{id: 1, title: "A Thing"}

iex(2)> Map.fetch(map, :title)
{:ok, "A Thing"}

A few things to note about maps:

  • The order of the returned map may not be the same as the definition.
  • You can use string keys: %{"id" => 1}
  • If you mix string/atom keys, the atom must be last or a SyntaxError will be raised.

Ranges

A range represents a sequence of one or many, ascending or descending, consecutive integers.

Ranges can be either increasing (first <= last) or decreasing (first > last). Ranges are also always inclusive.

iex(1)> range = 1..3
1..3

iex(2)> first..last = range
1..3

iex(3)> first
1

iex(4)> last
3

Conclusion

Thanks for reading the first article in this series!   We covered the basic data types of Elixir and used IEx to help demonstrate the concepts with a few examples.

Follow our twitter account @phxroad and hit me up on Twitter if you have any questions or ideas.

Elixir Series

Author image

About Troy Martin

Ruby, Elixir and Javascript Software Developer.