Boolean logic and conditional functions.

Functions

and core

fn (lazy x: Any, rest): Any

Returns the first falsy value, or the last value if all are truthy. Falsy is false, null, and Err — everything else (including 0, "", [], and {}) is truthy, exactly as in if/cond.

Direct calls short-circuit left to right: arguments after the first falsy one are never evaluated, so and(is-map(x), get(x, "k")) is a safe guard. Only dynamic uses — spread arguments, or and passed as a function value — evaluate every argument eagerly.

Example

and(true, true)       // true
and(true, false)      // false
and(1, 2, 3)          // 3 (all truthy, returns last)
and(1, null, 3)       // null (first falsy; 3 never evaluated)
and("", "x")          // "x" — "" is a value, not falseness
and(false, fail("x")) // false — short-circuit skips the fail

if core

fn (pred: Any, lazy then: Any): Any
fn (pred: Any, lazy then: Any, lazy else: Any): Any

If pred is truthy, return then, otherwise return else. Arguments are lazy-evaluated.

Example

if(true, "yes", "no")   // "yes"
if(false, "yes", "no")  // "no"

// Lazy evaluation prevents errors
x 0
if(eq(x, 0), "zero", div(10, x))  // "zero" - div never called

is-truthy core

fn (lazy value: Any): Bool

Check if value is truthy. Falsy is false, null, and Err — everything else (including 0, "", [], and {}) is truthy, exactly as in if/cond. Test emptiness with is-empty.

Example

is-truthy(true)     // true
is-truthy(0)        // true
is-truthy("")       // true
is-truthy(false)    // false
is-truthy(null)     // false
is-truthy(err("e")) // false

not core

fn (lazy x: Any): Bool

Negate x. If x is truthy, return false, otherwise return true.

Example

not(true)   // false
not(false)  // true
not(null)   // true
not(1)      // false
not(0)      // false (0 is truthy; falsy is only false, null, Err)

or core

fn (lazy x: Any, rest): Any

Returns the first truthy value, or the last value if all are falsy. Falsy is false, null, and Err — everything else (including 0, "", [], and {}) is truthy, exactly as in if/cond. This makes or the null-coalescing idiom: or(::hot::ctx/get(k), default) yields the default only when the value is absent, never because it is empty or zero. Test emptiness explicitly with is-empty.

Direct calls short-circuit left to right: arguments after the first truthy one are never evaluated, so an expensive fallback in or(cached, recompute()) only runs when needed. Only dynamic uses — spread arguments, or or passed as a function value — evaluate every argument eagerly.

Example

or(true, false)   // true
or(null, 0, 42)   // 0 (0 is truthy; 42 never evaluated)
or(null, false)   // false (all falsy, returns last)
or("", "x")       // "" — "" is a value, not falseness
or(err("e"), "x") // "x" — Err is falsy, so or() recovers
or(true, fail("x")) // true — short-circuit skips the fail