Elixir Types
Posted on November 08, 2014 by Clive in Elixir
Elixir has many of the types that you would expect from a modern programming language. The following list details these:
what may or may not surprise you is that strings are absent from this list. That is because strings are lists, they are either lists of chars (character codes), denoted by single quotes or lists of binaries as denoted by double quotes. In Elixir the concept of a string as used in imperative languages is the double quoted form and is stored as a sequence of bytes in UTF-8 encoding. Strings and string operations will be covered in a different post. Integers are whole numbers and can be of arbitrary size, usually dictated by the total amount of memory that you have in your system. This value type can be represented in several different ways: decimal (1234), hexadecimal (0xcafe), octal (0o765) or binary (0b101010) These conform to IEEE 754 double precision standard, meaning that they have about 16 digits of accuracy and a maximum exponent of 10308. Standard decimal-point numbers with an optional trailing exponent are valid: are all valid. For those that have not come across atoms before, they are constants the value of which is the same as its name. In Ruby they are called symbols and look exactly the same: they can be made up of any combination of characters, but if you want to use anything that is not a valid letter, digit, at-signs or underscore, then you need to enclose it in double quotes: A range is represented by start..end, where start and end are values of any type. They are usually integers to allow iteration. Elixir has its own particular syntax for regular expression patterns. The patterns themselves are provided by PCRE.
The syntax itself is: ~r{ From Elixir Regex:
The modifiers available when creating a Regex are: Example usage: the delimiters ‘{‘ and ‘}’ can be replaced with any matching non-alphanumeric characters, like ‘%’ or ‘/‘. If ‘/‘ is used, then any ‘/‘ will need to be escaped in the regular expression pattern. PID’s are process ids. They are references to local or remote Elixir processes. PID’s are created automatically when processes are spawned.
To get access to the PID of the current process you call self
PID’s look like *<0.46.1>* A port is reference to a resource, typically external to the application like a file, something that can be read from and/or written to. Tuples are collections of values written between ‘{‘ and ‘}’ with elements separated by commas: Tuples are immutable, meaning that once created they cannot be changed. The element values do not need to be the same for each element. Tuples are frequently used in pattern-matching: If the patterns on either side of the ‘=’ operator don’t match then: Tuples of different lengths are actually classed as different types. A Tuple with 2 elements is called a 2-tuple, with 3 elements a 3-tuple and so on. Lists are represented by collections of values contained between ‘[‘ and ‘]’ and the values are separated by commas. An empty list is represented by *[]* A list is not an array, but a linked data structure which consists of a head and a tail. The head of a list is a value and the tail is itself a list. Lists are generally traversed in sequence and this is cheap to do. To access elements in a list randomly is an expensive operation. Lists will be further discussed in a different post. Because it is a frequent requirement to have lists of key/value pairs, Elixir provides us some syntatic sugar: In Elixir, this is represented as a list of 2-tuples *[{:key1, “value1”}, {:key2, “value2”}]* A map is a collection of key/value pairs. The keys in a map do not necessarily need to be strings. They can be atoms, tuples, or any other matchable type. Also the keys in a map do not need to be of the same type. Values can be extracted from a Map using square bracket syntax: If the keys are atoms then we can use some syntatic sugar and treat it like a keyword list. In this case we can access the elements using dot-notation: Question: why have both Keyword lists and Maps?
Answer: because maps only allow unique keys, are highly optimised and can be used in pattern-matching, whereas in keyword lists the keys need not be unique and are generally used to pass around commandline arguments or options. Binaries are available in case you need to access data as a sequence of bits and bytes. Binary literals and delineated by *<<* and >> Structs are a complex data type that requires a full post all to themselves. With the whirlwind tour of types over, our next stop will be functions…
Integers
Floating-point Numbers
1.0
0.11111
1e12
3.14e-5
Atoms
:atom
:”this contains spaces”
:”func/3”
Ranges
iex(1)> 1..10
1..10
iex(2)> 1..10 |> Enum.map(&(&1))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Regular Expressions
Regex.scan ~r{[aeiou]}, "caterpillar"
[["a"], ["e"], ["i"], ["a"]]
PID’s
Ports
Tuples
iex(1)> {1,2,3,4}
{1,2,3,4}
iex(2)> {:ok, "This is a tuple", 42}
{:ok, "This is a tuple", 42}
iex(5)> {:ok, count, action} = {:ok, 128, "delete"}
{:ok, 128, "delete"}
iex(6)> count
128
iex(7)> action
"delete"
iex(8)> {:error, reason} = {:ok, 128, "delete"}
** (MatchError) no match of right hand side value: {:ok, 128, "delete"}
Lists
iex(1)> [1,2,3]
[1,2,3]
iex(1)> [head | tail] = [1,2,3,4]
[1,2,3,4]
iex(2)> head
1
iex(3)> tail
[2,3,4]
Keyword Lists
iex(1)> [ key1: "value1", key2: "value2" ]
Maps
iex(1)> %{ "key1" => "value1", "key2" => "value2" }
iex(1)> postcode_towns = %{ "DN" => "Doncaster", "MK" => "Milton Keynes", "SW" => "Southwest London" }
%{ "DN" => "Doncaster", "MK" => "Milton Keynes", "SW" => "Southwest London" }
iex(2)> postcode_towns["DN"]
"Doncaster"
iex(1)> colours = %{ red: "#ff0000;", green: "#00ff00;", blue: "#0000ff;" }
%{ red: "#ff0000;", green: "#00ff00;", blue: "#0000ff;" }
iex(2)> colours.blue
"#0000ff;"
iex(3)> colours.pink
** (KeyError) key :pink not found in: %{blue: "#0000ff;", green: "#00ff00;", red: "#ff0000;"}
Binaries
Structs