Enums
Enums in Gleam are a way of modeling data that can be one of a few different variants. They must be declared before use, and the names of variants must be unique for the given module.
We've seen an enum already in this chapter- Bool
.
Bool is defined like this:
// A Bool is a value that is either `True` or `False`
enum Bool =
| True
| False
Enum variants can also contain other values, and these values can be extracted using a let binding.
enum User =
| LoggedIn(String) // A logged in user with a name
| Guest // A guest user with no details
let sara = LoggedIn("Sara")
let rick = LoggedIn("Rick")
let visitor = Guest
Destructuring
When given an enum we can pattern match on it to determine which variant it is and to assign names to any contained values.
fn get_name(user) {
case user {
| LoggedIn(name) -> name
| Guest -> "Guest user"
}
}
Enums can also be destructured with a let
binding.
enum Score =
| Points(Int)
let score = Points(50)
let Points(p) = score
p // => 50
Commonly used enums
Bool
pub enum Bool =
| True
| False
As seen above Gleam's Bool
type is an enum! Use it to answer yes/no
questions and to indicate whether something is True
or False
.
Result(value, error)
pub enum Result(value, reason) =
| Ok(value)
| Error(reason)
Gleam doesn't have exceptions of null
to represent errors in our programs,
instead we have the Result
type. If a function call fail wrap the returned
value in a Result
, either Ok
if the function was successful, or Error
if it failed.
pub fn lookup(name, phone_book) {
// ... we found a phone number in the phone book for the given name here
Ok(phone_number)
}
The Error
type needs to be given a reason for the failure in order to
return, like so:
pub enum MyDatabaseError =
| InvalidQuery
| NetworkTimeout
pub fn insert(db_row) {
// ... something went wrong connecting to a database here
Error(NetworkTimeout)
}
In cases where we don't care about the specific error enough to want to create
a custom error type, or when the cause of the error is obvious without further
detail, the Nil
type can be used as the Error
reason.
pub fn lookup(name, phone_book) {
// ... That name wasn't found in the phone book
Error(Nil)
}
When we have a Result
type returned to us from a function we can pattern
match on it using case
to determine whether we have an Ok
result or
an Error
result.
The standard library gleam/result
module contains helpful functions for
working with the Result
type, make good use of them!
Erlang interop
At runtime enum variants with no contained values become atoms. The atoms are
written in snake_case
rather than CamelCase
so LoggedIn
becomes
logged_in
.
Enum variants with contained values become tuples with a tag atom.
// Gleam
Guest
LoggedIn("Kim")
# Elixir
:guest
{:logged_in, "Kim"}
% Erlang
guest,
{logged_in, <<"Kim">>}.