Exploring gleam/bool
A good way of really understanding a programming language is to go deep into the standard library and really get to know every single function.
In this blog post, we will explore the bool module of the gleam standard library. I might look into other modules as well, but who knows 🤷 don't want to promise too much.
I'm going through the functions in alphabetical order, but you can just jump to the sections that you are most interested in.
and
pub fn and(a: Bool, b: Bool) -> Bool
At first, this function might seem odd. We already have the &&
operator and its behavior is the same:
fn and(a,b) {
a && b
}
However, it can be useful in combination with a higher order function.
import gleam/list
[ True, True, False, True]
|> list.fold(True,and)
// -> True
compare
pub fn compare(a: Bool, with b: Bool) -> Order
The compare function can be found in every module of the standard library and is used to compare two values of the same type.
import gleam/order
fn compare(a, b) {
case a,b {
True, True -> order.Eq
True, False -> order.Gt
False, True -> order.Lt
False, False -> order.Eq
}
}
It can be useful for ordering a list
import gleam/list
[ #(True,"A"),
#(True,"B"),
#(False,"C"),
#(True,"D"),
]
|> list.sort(fn(a,b){compare(a.0,b.0)})
|> list.map(fn(a){a.1})
// -> ["C","A","B","D"]
exclusive_nor
pub fn exclusive_nor(a: Bool, b: Bool) -> Bool
The XNOR gate might sound complicated, but it's actually just an equality check.
fn exclusive_nor(a,b){
a == b
}
It's one of those functions that you learn in university and then never use.
exclusive_or
pub fn exclusive_or(a: Bool, b: Bool) -> Bool
Similarly to the exclusive_nor, the exclusive_or is just the not equal check. It's not necessarily a function you actually need.
fn exclusive_or(a,b) {
a != b
}
guard
pub fn guard(
when requirement: Bool,
return consequence: a,
otherwise alternative: fn() -> a,
) -> a
The most useful function in the module is guard
.
fn guard(when, return, otherwise) {
case when {
True -> return
False -> otherwise()
}
}
It can be used for early returns.
use <- guard(i < 0, Error("Input Invalid"))
//you can now savely use i
lazy_guard
pub fn lazy_guard(
when requirement: Bool,
return consequence: fn() -> a,
otherwise alternative: fn() -> a,
) -> a
The lazy variant of the guard delays the computation of the return value.
lazy_guard(when,return,otherwise){
case when {
True -> return()
False -> otherwise()
}
}
A reason why you want to delay the computation could be because the computation takes very long.
use <- lazy_guard(!is_valid(input),gather_errors(input)())
nand
pub fn nand(a: Bool, b: Bool) -> Bool
You can use nand
instead of calling and
followed by not
.
fn nand(a,b) {
!and(a,b)
}
negate
pub fn negate(bool: Bool) -> Bool
The function negate
is the same as the operatior !
.
fn negate(bool) {
!bool
}
This might be useful in combination with a pipe operator
|> is_valid(name)
|> and(is_valid(address))
|> not
// -> False if either name or address is invalid.
nor
pub fn nor(a: Bool, b: Bool) -> Bool
Similar to nand
, nor
is the negation of or
.
fn nor(a,b) {
!or(a,b)
}
or
pub fn or(a: Bool, b: Bool) -> Bool
Instead of writing a || b
, you can also write or(a,b)
.
fn or(a,b) {
a || b
}
This is particular useful if you pass the function as argument.
[False, False, True, False]
|> list.fold(False,or)
// -> True
to_int
pub fn to_int(bool: Bool) -> Int
It sometimes makes sense to convert booleans into integers.
to_int(bool){
True -> 1
False -> 0
}
A use case could be to add a conditional offset
let left_offset = 42 + to_int(big_offset) * 100
to_string
pub fn to_string(bool: Bool) -> String
For debugging, you might want to convert a boolean into a string.
fn to_string(bool) {
True -> "True"
False -> "False"
}
Note that if a production use case, you might want to write that function yourself (to support different languages).
Subscribe to my newsletter
Read articles from Lucas Payr directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Lucas Payr
Lucas Payr
Hi there, I'm a Software developer and have been programming since 2010. I came in contact with functional programming when I did my master's in computer mathematics. I learned functional programming using Lisp, Prolog and Mathematica. But then I found my perfect language in Elm and never looked back. At my job, I work with Kotlin and Typescript, which work best by writing a hybrid of FP and OOP. Ever since I started working, I use field notes to track my thoughts and discoveries. My blog contains the best parts of those notes.