Given ๐ for Gleam
๐ guards aka early returns for Bool, Result, Option, and List types in a safe and ergonomic way for Gleam!
Installation
gleam add given@6
NOTICE: 6.0 contains a breaking change where return
and else_return
argument order were unified:
TO MAKE CERTAIN LOGIC IS NOT INVERTED BY ACCIDENT USE else_return
and/or
return
ARGUMENT LABELS BEFORE UPGRADING TO 6.0!
- Following functions have their return and else_return argument order switched:
given.that
given.any
given.all
given.not
given.any_not
given.all_not
Usage
//// All the functions contain labeled `else_return` and `return` callbacks.
////
//// Depending on readability where given is used one should use `return` or
//// `else_return` labels and positive or negative conditions.
////
//// The one not specified will become the happy path (or expected) path you
//// trot along as part of the `use` callback *body*.
////
//// The function form and argument order is always:
////
//// `condition_name(...data, else_return, return)`
////
//// Thus if you were to omit labels the positive case behind the `return` label
//// becomes the `use`-body.
////
//// Also see:
//// [Railway Oriented Programming](https://fsharpforfunandprofit.com/rop/).
import given
// Can use `return` labels:
fn given_not_example_1() {
let has_admin_role = True
use <- given.not(has_admin_role, return: fn() { "Denied!" })
"๐ Access granted!"
}
// Can use `else_return` labels:
fn given_not_example_2() {
let has_admin_role = False
use <- given.not(has_admin_role, else_return: fn() { "Access granted!" })
"โ Denied!"
}
fn given_that_example_1() {
let user_understood = True
use <- given.that(user_understood, else_return: fn() { "Woof!" })
"๐ก Bright!"
}
fn given_any_example_1() {
let is_admin = False
let is_editor = True
use <- given.any([is_admin, is_editor], else_return: fn() { "Cannot pass!" })
"๐ต Snap - I've got the power!"
}
fn given_all_example_1() {
let is_active = True
let is_confirmed = True
use <- given.all([is_active, is_confirmed], else_return: fn() { "Stop!" })
"๐ Ready, steady, go!"
}
fn given_any_not_example_1() {
let got_veggies = True
let got_spices = False
use <- given.any_not([got_veggies, got_spices], else_return: fn() {
"Preparing a soup!"
})
"๐ญ Ingredient missing..."
}
fn given_all_not_example_1() {
let is_android = False
let is_synthetic = False
use <- given.all_not([is_android, is_synthetic], else_return: fn() {
"I am a Cylon!"
})
"๐ชฆ Obsolete model detected."
}
fn given_when_example_1() {
let enabled_in_db = fn() { True }
use <- given.when(enabled_in_db, else_return: fn() { "User disabled!" })
"โ
User enabled"
}
fn given_when_not_example_1() {
let enabled_in_db = fn() { True }
use <- given.when_not(enabled_in_db, return: fn() { "User disabled!" })
"๐ข User enabled"
}
fn given_when_not_example_2() {
let enabled_in_db = fn() { False }
use <- given.when_not(enabled_in_db, else_return: fn() { "User enabled!" })
"โ User disabled"
}
fn given_empty_example_1() {
let list = []
use <- given.empty(list, else_return: fn() {
"Full as if you ate two large vegan ๐!"
})
"๐ธ Empty like vast space!"
}
fn given_non_empty_example_1() {
let list = [1]
use <- given.non_empty(list, else_return: fn() { "Empty like vast space! ๐ธ" })
"๐ Full as if you ate two large vegan!"
}
fn given_ok_example_1() {
let result = Ok("๐ Hello Joe, again!")
use val <- given.ok(in: result, else_return: fn(_error) {
"Joe is unreachable, now ๐."
})
val
}
fn given_any_ok_example_1() {
let results = [Ok("Happy"), Error("Sad")]
use _oks, _errors <- given.any_ok(in: results, else_return: fn(_errors) {
"All Error values!"
})
"๐ At least one Ok values!"
}
fn given_all_ok_example_1() {
let results = [Ok("Happy"), Ok("Glad")]
use _oks <- given.all_ok(in: results, else_return: fn(_oks, _errors) {
"At least one Error value!"
})
"๐๐ All Ok values"
}
fn given_error_example_1() {
let result = Error("๐ป Memory exhausted!")
use val <- given.error(in: result, else_return: fn(_ok) {
"Allocating memory..."
})
val
}
fn given_any_error_example_1() {
let results = [Ok("Happy"), Ok("Two")]
use _oks <- given.any_error(in: results, return: fn(_oks, _errors) {
"At least one Error occured!"
})
"๐ No Errors"
}
fn given_any_error_example_2() {
let results = [Ok("Happy"), Error("Sad")]
use _oks, _errors <- given.any_error(in: results, else_return: fn(_oks) {
"No Errors"
})
"๐ง At least one Error occured!"
}
fn given_all_error_example_1() {
let results = [Error("Sad"), Error("Lonely")]
use _errors <- given.all_error(in: results, else_return: fn(_oks, _errors) {
"Life is good!"
})
"โ Take care and learn to love yourself!"
}
import gleam/option.{None, Some}
fn given_some_example_1() {
let option = Some("๐ช One more penny")
use val <- given.some(in: option, else_return: fn() { "Nothing to spare!" })
val
}
fn given_any_some_example_1() {
let options = [Some("One"), None]
use _somes, _nones_count <- given.any_some(
in: options,
else_return: fn(_nones_count) { "Nothing at all." },
)
"๐
At least one Some!"
}
fn given_all_some_example_1() {
let options = [Some("Treasure Chest"), Some("Nugget")]
use _somes <- given.all_some(
in: options,
else_return: fn(_somes, _nones_count) { "Nothing at all" },
)
"๐
There is gold everywhere!"
}
fn given_none_example_1() {
let option = None
use <- given.none(in: option, else_return: fn(_some_value) {
"There is someone sleeping!"
})
"๐, aka None is in this bed!"
}
fn given_any_none_example_1() {
let options = [Some("One"), Some("Two")]
use _somes <- given.any_none(in: options, return: fn(_somes, _none_count) {
"None, detected in the system at least once."
})
"๐ง๐ง Only Somes here!"
}
fn given_any_none_example_2() {
let options = [Some("One"), None]
use _somes, _none_count <- given.any_none(
in: options,
else_return: fn(_somes) { "Only Somes here!" },
)
"๐ณ๏ธ, aka None, detected in the system at least once."
}
fn given_all_none_example_1() {
let options = [None, None]
use <- given.all_none(in: options, else_return: fn(_somes, _nones_count) {
"Someone tipped me :)!"
})
"๐ซ There is nothing in the jar..."
}
pub fn main() {
// Bool
given_not_example_1() |> echo
given_not_example_2() |> echo
given_that_example_1() |> echo
given_any_example_1() |> echo
given_all_example_1() |> echo
given_any_not_example_1() |> echo
given_all_not_example_1() |> echo
// Function
given_when_example_1() |> echo
given_when_not_example_1() |> echo
given_when_not_example_2() |> echo
// List
given_empty_example_1() |> echo
given_non_empty_example_1() |> echo
// Result
given_ok_example_1() |> echo
given_any_ok_example_1() |> echo
given_all_ok_example_1() |> echo
given_error_example_1() |> echo
given_any_error_example_1() |> echo
given_any_error_example_2() |> echo
given_all_error_example_1() |> echo
// Option
given_some_example_1() |> echo
given_any_some_example_1() |> echo
given_all_some_example_1() |> echo
given_none_example_1() |> echo
given_any_none_example_1() |> echo
given_any_none_example_2() |> echo
given_all_none_example_1() |> echo
}
Run usage examples above
git clone https://github.com/inoas/gleam-given.git
cd gleam-given
bin/run-examples
Further documentation can be found at https://hexdocs.pm/given.
Similar projects
See gond for multi-branch conditional
expression similar to if-else
, if
-else-if
-else
or cond
for Gleam.
Tags
guard
guard expression
guard clause
guard code
guard statement
early return
early exit
bool.guard
railway oriented programming
Either Monad
Try Monad
Development
gleam run # Run the project
gleam test # Run the tests