ilusm.dev

res

Result type aligned with try - construct {val, err} success and failure values, check ok/error status, unwrap (throws on error), unwrap with a default, expect with a custom error message, map the success value, map the error, chain with then, fall back with or-else, tap for side-effects, and zip two results into a pair.

Load with: use res

What this module does

res provides a small, deliberate set of combinators for {val, err} result objects - the same shape that ilusm's built-in try produces. This lets you write null-safe, error-aware pipelines without nested if chains.

The module is intentionally minimal: it covers single-value-in / single-value-out transformations. For list operations (sequence, partition, from-try) use the eru module.

Quick example

use res

# Construct
ok  = res.ok(42)
bad = res.bad("not found")

# Check
prn(res.isok(ok))   # tru
prn(res.iserr(bad)) # tru

# Unwrap
prn(res.val(ok))    # 42
prn(res.err(bad))   # "not found"
res.unw(ok)         # 42  (throws if error)
res.unwor(bad, 0)   # 0   (default on error)
res.expct(bad, "lookup failed")  # throws "lookup failed: not found"

# Pipelines
result = res.ok(5)
    |> res.map(\(v) v * 2)        # ok(10)
    |> res.then(\(v) res.ok(v+1)) # ok(11)
    |> res.tap(\(v) prn("got " + str(v)))

# Zip two results
pair = res.zip(res.ok(1), res.ok(2))  # ok([1, 2])

Functions

Constructors

res.ok(v)

Returns {val: v, err: nil}. The success case.

res.bad(e)

Returns {val: nil, err: e}. The failure case. e is typically a string or structured error object.

Inspection

res.isok(r)

Returns tru if r.err is nil.

res.iserr(r)

Returns tru if r.err is not nil.

res.val(r)

Returns the val field.

res.err(r)

Returns the err field.

Unwrapping

res.unw(r)

Returns r.val if ok; throws r.err as a string if error.

res.unwor(r, default)

Returns r.val if ok, or default if error. Never throws.

res.expct(r, msg)

Returns r.val if ok; throws "msg: err" if error. Use for assertions with context.

Chaining

res.map(r, fn)

If ok, returns res.ok(fn(r.val)). If error, passes r through unchanged.

res.mperr(r, fn)

If error, returns res.bad(fn(r.err)). If ok, passes r through unchanged.

res.then(r, fn)

If ok, calls fn(r.val) - which must itself return a result. If error, passes r through. Like flatMap.

res.orls(r, fb)

If ok, passes r through. If error, calls fb(r.err) for a fallback result.

res.tap(r, fn)

If ok, calls fn(r.val) for side-effects then returns r unchanged. Useful for logging.

res.zip(a, b)

If both ok, returns res.ok([a.val, b.val]). If either is an error, returns the first failing result.

Notes

  • Requires trl and eru.