Exploring gleam/bool

Lucas PayrLucas Payr
4 min read

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).

0
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.