Non-Enumerables
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
Setup
Ensure you type the ea
keyboard shortcut to evaluate all Elixir cells before starting. Alternatively you can evaluate the Elixir cells as you read.
Enumeration With Non-Enumerables
Data types that do not contain multiple elements are not enumerable. However, it’s still sometimes useful to enumerate over non-enumerable data types.
Even though you can’t enumerate over them directly, the trick is to convert non-enumerable data into an enumerable data type.
Integers
How would you convert integers into an Enumerable?
You can use the Integer.digits/1
function.
Integer.digits(123)
Your Turn
In the Elixir cell below, convert the integer 4389
into a list of digits.
Tuples
Despite being so similar to lists, tuples are not considered collections. That’s primarily because they are intended as fixed-sized containers, and any case that requires enumeration would likely be better served with lists.
To get around this if needed, you can convert a tuple to a list with Tuple.to_list/1
.
Now you have a list that you can work with as a collection if necessary.
However, if you find yourself doing this often, it may be a better choice to start with a list instead of a tuple.
Tuple.to_list({1, 2, 3})
Strings
Strings are not enumerable, however there are several methods to convert strings to lists.
Strings can be converted into lists with either String.graphemes/1
or String.codepoints/1
.
Under the hood, strings are represented with a codepoint. A codepoint is an integer that represents
the character. Each character such as "a"
has a corresponding codepoint. That’s why the
function is called String.codepoints/1
.
String.split("abc", "", trim: true)
String.codepoints("abcdefghijklmnopqrstuvwxyz")
For example, the code point for the letter a
is 97
. Lowercase and uppercase letters have
different codepoints.
You can find the code point of any character by using ?
in Elixir. Evaluate the Elixir cell below
to see how ?a
returns 97
.
?a
If you are curious, the full list of representable characters is called the The Unicode Standard.
See this table for alphabetical characters and their code point values. You do not need to memorize these values! You only need to be aware that each character has a corresponding codepoint.
Utils.table(:unicode)
String.graphemes/1
Some special characters are actually multiple characters combined.
You’ll notice that é is actually 2 characters if you use String.codepoints/1
.
Each character has its own codepoint.
String.codepoints("é")
We use grapheme to refer to special characters that may contain multiple codepoints.
Therefore, use String.graphemes
when you want to convert the string to a list without separating special characters
formed from multiple codepoints.
String.graphemes("é")
Alternatively, you can use String.split/3
to split a string based on some value.
For example, we can split a string by every comma like so:
String.split("a,b,c,d", ",")
You can use this to accomplish the same behavior as String.graphemes/1
by passing a string as the second argument.
However this leaves whitespace from the start and end of the string in.
String.split("abcde", "")
You can trim whitespace using the [trim: true]
option.
String.split("abcde", "", trim: true)
Now your string is an enumerable list of characters.
Your Turn
In the Elixir cell below, convert the string "Hello, world!"
into a list of single characters.
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 non enumerables section"