Built-In Elixir Modules
Mix.install([
{:kino, github: "livebook-dev/kino", override: true},
{:kino_lab, "~> 0.1.0-dev", github: "jonatanklosko/kino_lab"},
{:vega_lite, "~> 0.1.4"},
{:kino_vega_lite, "~> 0.1.1"},
{:benchee, "~> 0.1"},
{:ecto, "~> 3.7"},
{:math, "~> 0.7.0"},
{:faker, "~> 0.17.0"},
{:utils, path: "#{__DIR__}/../utils"}
])
Navigation
Overview
Elixir provides a great deal of functionality in built-in modules.
In general, each data type or common behavior has a built-in module containing related functions for dealing with that data type.
While it is unnecessary to memorize every function in every module, it’s essential to be familiar with the built-in modules to know when to reach for them.
The Kernel Module
The Kernel is the core of everything Elixir.
Even the operators that you’ve been using are simply an alternative syntax to using functions in the Kernel.
Kernel.+(3, 3)
Kernel
contains many functions for determining a values type such as is_atom/1
, is_binary/1
, is_map/1
, and is_integer/1
.
true = Kernel.is_map(%{})
true = Kernel.is_atom(:an_atom)
true = Kernel.is_binary("")
true = Kernel.is_integer(1)
We can use Kernel
functions without using the Kernel
namespace.
is_map(%{})
The Kernel
is reasonably large. Remember, our goal is not to memorize every function but to develop familiarity with repeated practice.
Your Turn
In the Elixir cell below, use the correct function from Kernel
to determine if each value below matches its type.
The first is_a_atom
value is filled in to demonstrate the goal.
Replace nil
with your answers.
atom = :example
map = %{}
string = ""
integer = 1
float = 1.0
boolean = true
list = []
tuple = {}
is_a_atom = is_atom(atom)
is_a_map = nil
is_a_string = nil
is_a_integer = nil
is_a_float = nil
is_a_boolean = nil
is_a_list = nil
is_a_tuple = nil
Utils.feedback(:is_type, [
is_a_map,
is_a_string,
is_a_integer,
is_a_float,
is_a_boolean,
is_a_list,
is_a_tuple
])
The Integer Module
The Integer module contains functionality related to Integers.
Here are a few functions to get you started.
-
parse/2
parses integers from strings. -
digits/2
splits an integer into a list of digits. -
gcd/2
find the greatest common divisor between two integers.
Your Turn
Use the Integer.parse/2
function to convert "2"
to an integer. Notice that the return value should
be {2, ""}
Because Integer.parse/2
returns a tuple with the parsed integer and the remaining string.
Replace nil
with your answer.
parsed = nil
Utils.feedback(:integer_parse, parsed)
Use the Integer.digits/2
function to split 123456789
into a list of integers.
Replace nil
with your answer.
digits = nil
Utils.feedback(:integer_digits, digits)
Use the Integer.gcd/2
function to determine the greatest common denominator of
10
and 15
. The greatest common divisor (GCD) is the largest
positive integer that divides both 10 and 15 evenly.
Replace nil
with your answer.
gcd = nil
Utils.feedback(:gcd, gcd)
The String Module
The String module contains functionality related to strings.
Here are a few common functions to get you started.
-
at/2
gets the value at the index of a string. -
contains?/2
check if a string contains a value. -
capitalize/2
capitalize the first letter in a string and leaves the rest lowercase. -
split/3
split the string into a list of words. -
trim/1
remove whitespace from a string. -
upcase/1
convert a string to ALL CAPS.
Indexes
You can imagine a string like a list of characters. However, be warned this is only a mental model, strings are not actually implemented as lists.
flowchart TB
subgraph Characters
S
T
R
I
N
G
end
subgraph Indexes
direction TB
S --- 0
T --- 1
R --- 2
I --- 3
N --- 4
G --- 5
end
Notice that the index starts with 0, not 1, just like lists.
So the character at index 1 in "hello"
would be "e"
.
flowchart TB
subgraph Characters
H
E
L1[L]
L2[L]
O
end
subgraph Indexes
direction TB
H --- 0
E --- 1
L1 --- 2
L2 --- 3
O --- 4
end
Your Turn
Use the String.at/2
function to get the character at index 2
of "hello"
.
The result should be the character l
.
Replace nil
with your answer.
answer = nil
Utils.feedback(:string_at, answer)
Use the String.contains?/2
function to determine if "Hello"
contains "lo"
. Replace nil
with your answer.
answer = nil
Utils.feedback(:string_contains, answer)
Use String.capitalize/2
to capitalize "hello"
. Replace nil
with your answer.
answer = nil
Utils.feedback(:string_capitalize, answer)
Use String.split/3
to split the following comma-separated list of strings into a list of words.
Replace nil
with your answer.
string = "have,a,great,day"
words = nil
Utils.feedback(:string_split, words)
Use String.trim/1
to remove whitespace from the following string.
Replace nil
with your answer.
string = " hello! "
trimmed_string = nil
Utils.feedback(:string_trim, trimmed_string)
Use String.upcase/1
to convert the following string to all caps.
Replace nil
with your answer.
string = "hello"
uppercase_string = nil
Utils.feedback(:string_upcase, uppercase_string)
The List Module
The List module contains functionality related to lists.
Here are a few common functions to get you started.
-
delete_at/2
remove an element at an index in a list. -
first/2
retrieve the first element in a list similar tohd/1
or pattern matching on the head and tail of a list. -
flatten/2
flatten nested lists within a list. -
insert_at/3
insert an element at a specified index within a list. -
last/2
retrieve the last element in a list. -
update_at/3
update an element at a specified index within a list. -
zip/1
combine elements from multiple lists into a single list of tuples.
The delete_at/2
, insert_at/3
and update_at/3
functions do not mutate the original list. Instead, they create a new copy of the original list with the operation applied to it.
Your Turn
Use delete_at/2
to remove 2
from this list.
list = [1, 2, 3]
first/2
retrieves the first element in a list. We can also use hd/1
, Enum.at/2
, or pattern matching.
head = List.first([1, 2, 3])
[head | _tail] = [1, 2, 3]
head
hd([1, 2, 3])
head = Enum.at([1, 2, 3], 0)
Try pattern matching, List.first/2
, Enum.at/2
, and hd/1
to retrieve the first element of
the list below.
list = [1, 2, 3]
Use List.flatten/1
to flatten the following list into [1, 2, 3, 4, 5, 6, 7, 8, 9]
list = [1, 2, [3, 4, 5], 6, [7, [8, [9]]]]
Use List.insert_at/3
to insert 2
into the following list to make [1, 2, 3]
.
List.insert_at([1, 3], 1, 2)
Use List.last/2
to retrieve the last element 10000
in the list below.
list = Enum.to_list(1..10000)
Use List.update_at/3
to replace 4
with 2
in the following list to make [1, 2, 3]
.
list = [1, 4, 3]
Use List.zip/1
to combine these two lists to make [{"a", 1}, {"b", 2}, {"c", 3}]
.
lista = ["a", "b", "c"]
listb = [1, 2, 3]
The Map Module
The Map module contains functionality related to maps.
Here are a few common functions to get you started.
-
get/3
retrieve values in a map. -
put/3
put a value into a map. -
keys/1
list the keys in a map. -
delete/2
remove a key and value from a map. -
merge/2
merge two maps together. -
values/1
list the values in a map.
Keep in mind operations do not mutate a value.
For example, if we use Map.put/3
to put a new value in a map, the original variable is not
changed. Functions return a new value rather than modifying the original one.
original_map = %{}
new_map = Map.put(original_map, :key, "value")
So the original_map
is still an empty map %{}
.
original_map
And the new_map
has been bound to the result of Map.put/3
.
new_map
Your Turn
Use Map.get/3
to retrieve the value for the :hello
key in the following map.
Replace nil
with your answer.
map = %{hello: "world"}
retrieved_value = nil
Utils.feedback(:map_get, retrieved_value)
Use Map.put/3
to add the key :two
with the value 2
to the following map. Replace nil
with your answer.
map = %{one: 1}
new_map = nil
Utils.feedback(:map_put, new_map)
Use Map.keys/1
to retrieve the keys for the following map. Replace nil
with your answer.
map = %{key1: 1, key2: 2, key3: 3}
keys = nil
Utils.feedback(:map_keys, keys)
Use Map.delete/2
to remove :key1
from the following map.
map = %{key1: 1, key2: 2, key3: 3}
new_map = nil
Utils.feedback(:map_delete, new_map)
Use Map.merge/2
to combine %{one: 1}
and %{two: 2}
. Replace nil
with your answer.
merged_map = nil
Utils.feedback(:merged_map, merged_map)
Use Map.values/1
to retrieve the values in the following map. Replace nil
with your answer.
map = %{key1: 1, key2: 2, key3: 3}
values = nil
Utils.feedback(:map_values, values)
The Keyword Module
The Keyword module contains functionality related to keyword lists.
Here are a few common functions to get you started.
-
get/3
retrieve values in a keyword list. -
keys/1
list the keys in a keyword list. -
keyword?/1
check if some data is a keyword list.
We often use keyword lists to provide optional arguments to a function.
For example, IO.inspect/2
has many optional arguments
Including :label
.
IO.inspect("world", label: "hello")
Under the hood, these functions may use Keyword.get/3
to retrieve optional arguments or provide
default arguments.
defmodule MyIO do
def inspect(value, opts \\ []) do
label = Keyword.get(opts, :label, "default label")
"#{label}: #{value}"
end
end
MyIO.inspect("world")
MyIO.inspect("world", label: "hello")
Your Turn
Use Keyword.get/3
to access the value for the :color
key in the following keyword list.
Replace nil
with your answer.
options = [color: "red"]
color = nil
Utils.feedback(:keyword_get, color)
Use the Keyword.keys/1
function to list all of the keys in the following keyword list.
Replace nil
with your answer.
options = [one: 1, two: 2, three: 3]
keys = nil
Utils.feedback(:keyword_keys, keys)
Use the Keyword.keyword?/1
function to determine if the following is a keyword list.
Replace nil
with your answer.
keyword_list = [key: "value"]
is_keyword_list = nil
Utils.feedback(:keyword_keyword?, is_keyword_list)
Further Reading
There are more built-in modules and functions beyond the scope of this introductory reading. The Elixir documentation further examples and information on the built-in modules.
Commit Your Progress
Run the following in your command line from the project folder to track and save your progress in a Git commit.
$ git add .
$ git commit -m "finish built-in modules section"