//// A type with two possible values, `True` and `False`. Used to indicate whether
//// things are... true or false!
////
//// It is often clearer and offers more type safety to define a custom type
//// than to use `Bool`. For example, rather than having a `is_teacher: Bool`
//// field consider having a `role: SchoolRole` field where `SchoolRole` is a custom
//// type that can be either `Student` or `Teacher`.
/// Returns the and of two bools, but it evaluates both arguments.
///
/// It's the function equivalent of the `&&` operator.
/// This function is useful in higher order functions or pipes.
///
/// ## Examples
///
/// ```gleam
/// assert and(True, True)
/// ```
///
/// ```gleam
/// assert !and(False, True)
/// ```
///
/// ```gleam
/// assert !and(False, True)
/// ```
///
/// ```gleam
/// assert !and(False, False)
/// ```
///
pub fn and(a: Bool, b: Bool) -> Bool {
a && b
}
/// Returns the or of two bools, but it evaluates both arguments.
///
/// It's the function equivalent of the `||` operator.
/// This function is useful in higher order functions or pipes.
///
/// ## Examples
///
/// ```gleam
/// assert or(True, True)
/// ```
///
/// ```gleam
/// assert or(False, True)
/// ```
///
/// ```gleam
/// assert or(True, False)
/// ```
///
/// ```gleam
/// assert !or(False, False)
/// ```
///
pub fn or(a: Bool, b: Bool) -> Bool {
a || b
}
/// Returns the opposite bool value.
///
/// This is the same as the `!` or `not` operators in some other languages.
///
/// ## Examples
///
/// ```gleam
/// assert !negate(True)
/// ```
///
/// ```gleam
/// assert negate(False)
/// ```
///
pub fn negate(bool: Bool) -> Bool {
!bool
}
/// Returns the nor of two bools.
///
/// ## Examples
///
/// ```gleam
/// assert nor(False, False)
/// ```
///
/// ```gleam
/// assert !nor(False, True)
/// ```
///
/// ```gleam
/// assert !nor(True, False)
/// ```
///
/// ```gleam
/// assert !nor(True, True)
/// ```
///
pub fn nor(a: Bool, b: Bool) -> Bool {
!{ a || b }
}
/// Returns the nand of two bools.
///
/// ## Examples
///
/// ```gleam
/// assert nand(False, False)
/// ```
///
/// ```gleam
/// assert nand(False, True)
/// ```
///
/// ```gleam
/// assert nand(True, False)
/// ```
///
/// ```gleam
/// assert !nand(True, True)
/// ```
///
pub fn nand(a: Bool, b: Bool) -> Bool {
!{ a && b }
}
/// Returns the exclusive or of two bools.
///
/// ## Examples
///
/// ```gleam
/// assert !exclusive_or(False, False)
/// ```
///
/// ```gleam
/// assert exclusive_or(False, True)
/// ```
///
/// ```gleam
/// assert exclusive_or(True, False)
/// ```
///
/// ```gleam
/// assert !exclusive_or(True, True)
/// ```
///
pub fn exclusive_or(a: Bool, b: Bool) -> Bool {
a != b
}
/// Returns the exclusive nor of two bools.
///
/// ## Examples
///
/// ```gleam
/// assert exclusive_nor(False, False)
/// ```
///
/// ```gleam
/// assert !exclusive_nor(False, True)
/// ```
///
/// ```gleam
/// assert !exclusive_nor(True, False)
/// ```
///
/// ```gleam
/// assert exclusive_nor(True, True)
/// ```
///
pub fn exclusive_nor(a: Bool, b: Bool) -> Bool {
a == b
}
/// Returns a string representation of the given bool.
///
/// ## Examples
///
/// ```gleam
/// assert to_string(True) == "True"
/// ```
///
/// ```gleam
/// assert to_string(False) == "False"
/// ```
///
pub fn to_string(bool: Bool) -> String {
case bool {
False -> "False"
True -> "True"
}
}
/// Run a callback function if the given bool is `False`, otherwise return a
/// default value.
///
/// With a `use` expression this function can simulate the early-return pattern
/// found in some other programming languages.
///
/// In a procedural language:
///
/// ```js
/// if (predicate) return value;
/// // ...
/// ```
///
/// In Gleam with a `use` expression:
///
/// ```gleam
/// use <- guard(when: predicate, return: value)
/// // ...
/// ```
///
/// Like everything in Gleam `use` is an expression, so it short circuits the
/// current block, not the entire function. As a result you can assign the value
/// to a variable:
///
/// ```gleam
/// let x = {
/// use <- guard(when: predicate, return: value)
/// // ...
/// }
/// ```
///
/// Note that unlike in procedural languages the `return` value is evaluated
/// even when the predicate is `False`, so it is advisable not to perform
/// expensive computation nor side-effects there.
///
///
/// ## Examples
///
/// ```gleam
/// let name = ""
/// use <- guard(when: name == "", return: "Welcome!")
/// "Hello, " <> name
/// // -> "Welcome!"
/// ```
///
/// ```gleam
/// let name = "Kamaka"
/// use <- guard(when: name == "", return: "Welcome!")
/// "Hello, " <> name
/// // -> "Hello, Kamaka"
/// ```
///
pub fn guard(
when requirement: Bool,
return consequence: a,
otherwise alternative: fn() -> a,
) -> a {
case requirement {
True -> consequence
False -> alternative()
}
}
/// Runs a callback function if the given bool is `True`, otherwise runs an
/// alternative callback function.
///
/// Useful when further computation should be delayed regardless of the given
/// bool's value.
///
/// See [`guard`](#guard) for more info.
///
/// ## Examples
///
/// ```gleam
/// let name = "Kamaka"
/// let inquiry = fn() { "How may we address you?" }
/// use <- lazy_guard(when: name == "", return: inquiry)
/// "Hello, " <> name
/// // -> "Hello, Kamaka"
/// ```
///
/// ```gleam
/// import gleam/int
///
/// let name = ""
/// let greeting = fn() { "Hello, " <> name }
/// use <- lazy_guard(when: name == "", otherwise: greeting)
/// let number = int.random(99)
/// let name = "User " <> int.to_string(number)
/// "Welcome, " <> name
/// // -> "Welcome, User 54"
/// ```
///
pub fn lazy_guard(
when requirement: Bool,
return consequence: fn() -> a,
otherwise alternative: fn() -> a,
) -> a {
case requirement {
True -> consequence()
False -> alternative()
}
}