Lowbar

A comprehensive utility plugin for ARO. Qualifiers and actions for working with collections, objects, and values — expressed in plain language, not callbacks. With thanks to the Underscore.js community, whose work inspired Lowbar's API design.

71 Qualifiers 5 Actions Swift Plugin v1.0.0

ARO is a declarative language where operations read like business requirements. Lowbar extends ARO's vocabulary with the utility functions you reach for every day — filtering collections, reshaping objects, checking types, generating sequences — all accessible through ARO's qualifier syntax.

(* Find all active admins and extract their names *)
Create the <users> with [
    { name: "Alice", role: "admin", active: true },
    { name: "Bob",   role: "user",  active: true },
    { name: "Eve",   role: "admin", active: false }
].

Compute the <active-admins: lowbar.where> from the <users> with { role: "admin", active: true }.
Compute the <names: lowbar.pluck> from the <active-admins> with { field: "name" }.
(* names = ["Alice"] *)

Installation

Add Lowbar to your ARO project with a single command:

aro add https://github.com/arolang/Lowbar.git

Or copy the Plugins/lowbar/ directory manually into your application's Plugins/ folder. Either way, ARO discovers and compiles the plugin automatically on first run.

Your application should look like this:

MyApp/
├── main.aro
└── Plugins/
    └── lowbar/
        ├── plugin.yaml
        ├── Package.swift
        └── Sources/
            └── LowbarPlugin.swift

Requires Swift 5.9+ and the ARO Plugin SDK.

How It Works

Lowbar provides two kinds of tools: qualifiers that transform values inline, and actions that generate new data.

Qualifiers

Qualifiers transform a value using the <result: lowbar.qualifier> syntax. They read naturally as part of an ARO statement:

Compute the <reversed: lowbar.reverse> from the <items>.

Many qualifiers accept parameters through a with { } clause:

Compute the <top-three: lowbar.first> from the <items> with { n: 3 }.
Compute the <sorted: lowbar.sort-by> from the <users> with { field: "age" }.

Qualifiers also work inside expressions, applied directly to a variable:

Log <items: lowbar.reverse> to the <console>.

Actions

Actions are verb-based statements using the Lowbar. prefix (PascalCase handle):

Lowbar.Range the <numbers> with { stop: 10 }.
Lowbar.Random the <dice> with { min: 1, max: 6 }.

Collections

Functions for working with lists. These qualifiers let you slice, filter, reorder, and reshape collections with a single statement.

first

Compute the <result: lowbar.first> from the <list>.

Returns the first element of a list. Pass n to get the first N elements instead. Useful for peeking at the head of a collection or taking a fixed-size prefix.

Create the <items> with [5, 3, 8, 1, 9].

Compute the <head: lowbar.first> from the <items>.
(* head = 5 *)

Compute the <top-three: lowbar.first> from the <items> with { n: 3 }.
(* top-three = [5, 3, 8] *)

initial

Compute the <result: lowbar.initial> from the <list>.

Returns everything except the last element. Pass n to exclude the last N elements. The complement of last.

Compute the <without-tail: lowbar.initial> from [1, 2, 3, 4, 5].
(* without-tail = [1, 2, 3, 4] *)

Compute the <trimmed: lowbar.initial> from [1, 2, 3, 4, 5] with { n: 3 }.
(* trimmed = [1, 2] *)

last

Compute the <result: lowbar.last> from the <list>.

Returns the last element of a list. Pass n to get the last N elements. The mirror of first.

Compute the <tail: lowbar.last> from [1, 2, 3, 4, 5].
(* tail = 5 *)

Compute the <last-two: lowbar.last> from [1, 2, 3, 4, 5] with { n: 2 }.
(* last-two = [4, 5] *)

rest

Compute the <result: lowbar.rest> from the <list>.

Returns everything except the first element. Pass n to skip the first N elements. The complement of first.

Compute the <remaining: lowbar.rest> from [1, 2, 3, 4, 5].
(* remaining = [2, 3, 4, 5] *)

Compute the <after-third: lowbar.rest> from [1, 2, 3, 4, 5] with { n: 3 }.
(* after-third = [4, 5] *)

compact

Compute the <result: lowbar.compact> from the <list>.

Strips all falsy values from a list: nil, false, 0, and empty strings are removed. Everything else stays. Handy for cleaning up data before processing.

Create the <messy> with [0, 1, "", "hello", false, true, 42].
Compute the <clean: lowbar.compact> from the <messy>.
(* clean = [1, "hello", true, 42] *)

flatten

Compute the <result: lowbar.flatten> from the <list>.

Flattens a nested list into a single level. Deep flattening is the default — all nesting is unwound. Pass deep: false to flatten only one level.

Create the <nested> with [[1, 2], [3, [4, 5]], [6]].

Compute the <flat: lowbar.flatten> from the <nested>.
(* flat = [1, 2, 3, 4, 5, 6] *)

Compute the <shallow: lowbar.flatten> from the <nested> with { deep: false }.
(* shallow = [1, 2, 3, [4, 5], 6] *)

uniq

Compute the <result: lowbar.uniq> from the <list>.

Removes duplicate values, preserving first-seen order. For lists of objects, pass field to deduplicate by a specific property.

Compute the <unique: lowbar.uniq> from [1, 2, 2, 3, 3, 3].
(* unique = [1, 2, 3] *)

Create the <records> with [
    { id: 1, role: "admin" },
    { id: 2, role: "user" },
    { id: 3, role: "admin" }
].
Compute the <by-role: lowbar.uniq> from the <records> with { field: "role" }.
(* by-role = [{id: 1, role: "admin"}, {id: 2, role: "user"}] *)

shuffle

Compute the <result: lowbar.shuffle> from the <list>.

Returns a randomly reordered copy using the Fisher-Yates algorithm. Also works on strings, shuffling individual characters.

Compute the <shuffled: lowbar.shuffle> from [1, 2, 3, 4, 5].
(* shuffled = [3, 1, 5, 2, 4]  (random) *)

Compute the <anagram: lowbar.shuffle> from "hello".
(* anagram = "lhoel"  (random) *)

sample

Compute the <result: lowbar.sample> from the <list>.

Draws a random element from the list. Pass n to draw multiple elements without replacement.

Compute the <winner: lowbar.sample> from ["alice", "bob", "eve"].
(* winner = "bob"  (random) *)

Compute the <team: lowbar.sample> from ["alice", "bob", "eve"] with { n: 2 }.
(* team = ["eve", "alice"]  (random) *)

size

Compute the <result: lowbar.size> from the <value>.

Returns the number of elements in a list, characters in a string, or keys in an object. A universal length check.

Compute the <count: lowbar.size> from [10, 20, 30].
(* count = 3 *)

Compute the <len: lowbar.size> from "hello".
(* len = 5 *)

Compute the <fields: lowbar.size> from { host: "localhost", port: 8080 }.
(* fields = 2 *)

reverse

Compute the <result: lowbar.reverse> from the <value>.

Reverses the order of elements in a list, or characters in a string.

Compute the <backwards: lowbar.reverse> from [1, 2, 3].
(* backwards = [3, 2, 1] *)

Compute the <flipped: lowbar.reverse> from "ARO".
(* flipped = "ORA" *)

to-array

Compute the <result: lowbar.to-array> from the <value>.

Converts a value to a list. Strings become character arrays, objects become their values. Lists pass through unchanged.

Compute the <chars: lowbar.to-array> from "Hi".
(* chars = ["H", "i"] *)

Compute the <vals: lowbar.to-array> from { a: 1, b: 2 }.
(* vals = [1, 2] *)

Searching

Find elements by matching properties, check membership, and locate positions. Instead of callback predicates, Lowbar matches against the properties you provide in the with { } clause.

where

Compute the <result: lowbar.where> from the <list> with { key: value, ... }.

Filters a list of objects, keeping only those whose properties match every key-value pair in the with clause. The declarative alternative to writing filter callbacks.

Create the <users> with [
    { name: "Alice", role: "admin", active: true },
    { name: "Bob",   role: "user",  active: true },
    { name: "Eve",   role: "admin", active: false }
].

Compute the <admins: lowbar.where> from the <users> with { role: "admin" }.
(* admins = [{name: "Alice", ...}, {name: "Eve", ...}] *)

Compute the <active-admins: lowbar.where> from the <users> with { role: "admin", active: true }.
(* active-admins = [{name: "Alice", ...}] *)

find-where

Compute the <result: lowbar.find-where> from the <list> with { key: value }.

Returns the first object in the list that matches all given properties. When you only need one match, this is faster and more direct than where.

Compute the <first-admin: lowbar.find-where> from the <users> with { role: "admin" }.
(* first-admin = {name: "Alice", role: "admin", active: true} *)

reject-where

Compute the <result: lowbar.reject-where> from the <list> with { key: value }.

The inverse of where. Returns every object that does not match the given properties.

Compute the <non-admins: lowbar.reject-where> from the <users> with { role: "admin" }.
(* non-admins = [{name: "Bob", role: "user", active: true}] *)

contains

Compute the <result: lowbar.contains> from the <list> with { value: x }.

Returns true if the given value is present in the list.

Compute the <has-it: lowbar.contains> from [1, 2, 3] with { value: 2 }.
(* has-it = true *)

every

Compute the <result: lowbar.every> from the <list> with { key: value }.

Returns true if every object in the list matches the given properties. Without properties, checks that all values are truthy.

Compute the <all-active: lowbar.every> from the <users> with { active: true }.
(* all-active = false *)

Compute the <all-truthy: lowbar.every> from [1, 2, 3].
(* all-truthy = true *)

some

Compute the <result: lowbar.some> from the <list> with { key: value }.

Returns true if any object in the list matches the given properties.

Compute the <has-admin: lowbar.some> from the <users> with { role: "admin" }.
(* has-admin = true *)

index-of

Compute the <result: lowbar.index-of> from the <list> with { value: x }.

Returns the position of the first occurrence of a value, or -1 if not found.

Compute the <pos: lowbar.index-of> from ["a", "b", "c", "b"] with { value: "b" }.
(* pos = 1 *)

last-index-of

Compute the <result: lowbar.last-index-of> from the <list> with { value: x }.

Returns the position of the last occurrence of a value, or -1.

Compute the <pos: lowbar.last-index-of> from ["a", "b", "c", "b"] with { value: "b" }.
(* pos = 3 *)

sorted-index

Compute the <result: lowbar.sorted-index> from the <sorted-list> with { value: x }.

Determines the index at which a value should be inserted into an already-sorted list to maintain sort order.

Compute the <idx: lowbar.sorted-index> from [10, 20, 30, 40] with { value: 25 }.
(* idx = 2 *)

find-index

Compute the <result: lowbar.find-index> from the <list> with { key: value }.

Returns the index of the first object matching the given properties, or -1.

Compute the <idx: lowbar.find-index> from the <users> with { role: "admin" }.
(* idx = 0 *)

find-last-index

Compute the <result: lowbar.find-last-index> from the <list> with { key: value }.

Like find-index, but searches from the end, returning the last matching position.

Compute the <idx: lowbar.find-last-index> from the <users> with { role: "admin" }.
(* idx = 2  (Eve is the last admin) *)

Grouping & Sorting

Organize, rank, and restructure collections by field values. These qualifiers take a field parameter to know which property to operate on.

sort-by

Compute the <result: lowbar.sort-by> from the <list> with { field: "..." }.

Returns a stably sorted copy of the list, ordered by the given field. Numeric fields are compared numerically. Pass order: "desc" for descending order.

Compute the <by-age: lowbar.sort-by> from the <users> with { field: "age" }.
Compute the <names: lowbar.pluck> from the <by-age> with { field: "name" }.
(* names = ["Eve", "Bob", "Alice"] *)

Compute the <oldest-first: lowbar.sort-by> from the <users> with { field: "age", order: "desc" }.
(* Alice (30) first, then Bob (25), then Eve (22) *)

group-by

Compute the <result: lowbar.group-by> from the <list> with { field: "..." }.

Splits a list into groups based on a field value. Returns an object where each key is a field value and each value is the list of matching items.

Compute the <by-role: lowbar.group-by> from the <users> with { field: "role" }.
(* by-role = { "admin": [{Alice}, {Eve}], "user": [{Bob}] } *)

count-by

Compute the <result: lowbar.count-by> from the <list> with { field: "..." }.

Like group-by, but returns the count per group instead of the items.

Compute the <counts: lowbar.count-by> from the <users> with { field: "role" }.
(* counts = { "admin": 2, "user": 1 } *)

index-by

Compute the <result: lowbar.index-by> from the <list> with { field: "..." }.

Creates a lookup object keyed by a unique field. Each value is the full object. Ideal for building dictionaries from lists.

Compute the <lookup: lowbar.index-by> from the <users> with { field: "name" }.
(* lookup = { "Alice": {name: "Alice", ...}, "Bob": {name: "Bob", ...}, ... } *)

pluck

Compute the <result: lowbar.pluck> from the <list> with { field: "..." }.

Extracts a single property from every object in the list. A concise shorthand for the most common projection operation.

Compute the <names: lowbar.pluck> from the <users> with { field: "name" }.
(* names = ["Alice", "Bob", "Eve"] *)

Compute the <ages: lowbar.pluck> from the <users> with { field: "age" }.
(* ages = [30, 25, 22] *)

partition

Compute the <result: lowbar.partition> from the <list> with { key: value }.

Splits a list into two: items that match the given properties, and items that don't. Returns [matching, non-matching].

Compute the <split: lowbar.partition> from the <users> with { active: true }.
(* split = [[{Alice}, {Bob}], [{Eve}]] *)

max

Compute the <result: lowbar.max> from the <list>.

Returns the maximum value in a list. For objects, pass field to compare by a specific property — the full object is returned, not just the field value.

Compute the <biggest: lowbar.max> from [5, 3, 8, 1].
(* biggest = 8 *)

Compute the <oldest: lowbar.max> from the <users> with { field: "age" }.
(* oldest = {name: "Alice", age: 30, ...} *)

min

Compute the <result: lowbar.min> from the <list>.

Returns the minimum value. Like max, accepts an optional field.

Compute the <youngest: lowbar.min> from the <users> with { field: "age" }.
(* youngest = {name: "Eve", age: 22, ...} *)

Set Operations

Combine and compare lists using set semantics. Pass the second list via the with { } clause.

without

Compute the <result: lowbar.without> from the <list> with { values: [...] }.

Returns a copy of the list with all specified values removed.

Compute the <filtered: lowbar.without> from [1, 2, 3, 4, 5] with { values: [2, 4] }.
(* filtered = [1, 3, 5] *)

union

Compute the <result: lowbar.union> from the <list> with { other: [...] }.

Combines two lists, keeping only unique values. Items from both lists appear in the result, but no duplicates.

Compute the <all: lowbar.union> from [1, 2, 3] with { other: [3, 4, 5] }.
(* all = [1, 2, 3, 4, 5] *)

intersection

Compute the <result: lowbar.intersection> from the <list> with { other: [...] }.

Returns only the values present in both lists.

Compute the <common: lowbar.intersection> from [1, 2, 3, 4] with { other: [3, 4, 5, 6] }.
(* common = [3, 4] *)

difference

Compute the <result: lowbar.difference> from the <list> with { other: [...] }.

Returns values that exist in the first list but not the second.

Compute the <only-mine: lowbar.difference> from [1, 2, 3, 4] with { other: [3, 4, 5] }.
(* only-mine = [1, 2] *)

Restructuring

Change the shape of your data — merge columns, split into pages, or convert between lists and objects.

zip

Compute the <result: lowbar.zip> from the <list> with { other: [...] }.

Merges two lists by pairing elements at corresponding positions. Produces a list of two-element arrays.

Compute the <pairs: lowbar.zip> from ["a", "b", "c"] with { other: [1, 2, 3] }.
(* pairs = [["a", 1], ["b", 2], ["c", 3]] *)

unzip

Compute the <result: lowbar.unzip> from the <list-of-pairs>.

The inverse of zip. Transposes a list of pairs into two separate lists.

Compute the <cols: lowbar.unzip> from [["a", 1], ["b", 2], ["c", 3]].
(* cols = [["a", "b", "c"], [1, 2, 3]] *)

object

Compute the <result: lowbar.object> from the <list-of-pairs>.

Converts a list of [key, value] pairs into an object. The reverse of pairs.

Compute the <obj: lowbar.object> from [["name", "Alice"], ["age", 30]].
(* obj = { name: "Alice", age: 30 } *)

chunk

Compute the <result: lowbar.chunk> from the <list> with { size: N }.

Splits a list into groups of the given size. The last chunk may be smaller if the list doesn't divide evenly. Useful for pagination and batch processing.

Compute the <pages: lowbar.chunk> from [1, 2, 3, 4, 5, 6, 7] with { size: 3 }.
(* pages = [[1, 2, 3], [4, 5, 6], [7]] *)

Numeric

Aggregate numeric values in a list.

sum

Compute the <result: lowbar.sum> from the <list>.

Adds up all numeric values. Non-numeric values are ignored.

Compute the <total: lowbar.sum> from [10, 20, 30].
(* total = 60 *)

avg

Compute the <result: lowbar.avg> from the <list>.

Calculates the arithmetic mean of all numeric values.

Compute the <mean: lowbar.avg> from [10, 20, 30].
(* mean = 20.0 *)

reduce

Compute the <result: lowbar.reduce> from the <list> with { op: "..." }.

Folds a list down to a single value using a built-in operation. Supports "+" (sum), "*" (product), and "join" (string concatenation). For "join", pass an optional separator.

Compute the <total: lowbar.reduce> from [1, 2, 3, 4] with { op: "+" }.
(* total = 10 *)

Compute the <product: lowbar.reduce> from [1, 2, 3, 4, 5] with { op: "*" }.
(* product = 120 *)

Compute the <sentence: lowbar.reduce> from ["hello", "world"] with { op: "join", separator: " " }.
(* sentence = "hello world" *)

Objects

Inspect, reshape, and merge objects. These qualifiers work on key-value structures.

keys

Compute the <result: lowbar.keys> from the <object>.

Returns all keys of an object as a sorted list.

Compute the <k: lowbar.keys> from { host: "localhost", port: 8080 }.
(* k = ["host", "port"] *)

values

Compute the <result: lowbar.values> from the <object>.

Returns all values of an object as a list.

Compute the <v: lowbar.values> from { host: "localhost", port: 8080 }.
(* v = ["localhost", 8080] *)

pairs

Compute the <result: lowbar.pairs> from the <object>.

Converts an object into a list of [key, value] pairs. The inverse of object.

Compute the <entries: lowbar.pairs> from { a: 1, b: 2 }.
(* entries = [["a", 1], ["b", 2]] *)

invert

Compute the <result: lowbar.invert> from the <object>.

Swaps keys and values. Values become keys, keys become values.

Create the <colors> with { red: "#ff0000", green: "#00ff00" }.
Compute the <lookup: lowbar.invert> from the <colors>.
(* lookup = { "#ff0000": "red", "#00ff00": "green" } *)

pick

Compute the <result: lowbar.pick> from the <object> with { keys: [...] }.

Returns a copy of the object containing only the listed keys. The allow-list approach to object filtering.

Create the <user> with { name: "Alice", email: "a@b.com", password: "secret" }.
Compute the <public: lowbar.pick> from the <user> with { keys: ["name", "email"] }.
(* public = { name: "Alice", email: "a@b.com" } *)

omit

Compute the <result: lowbar.omit> from the <object> with { keys: [...] }.

Returns a copy without the listed keys. The deny-list counterpart to pick.

Compute the <safe: lowbar.omit> from the <user> with { keys: ["password"] }.
(* safe = { name: "Alice", email: "a@b.com" } *)

defaults

Compute the <result: lowbar.defaults> from the <object> with { key: value, ... }.

Fills in missing properties with default values. Existing properties are never overwritten. The safe way to ensure an object has all required fields.

Create the <config> with { host: "localhost" }.
Compute the <full: lowbar.defaults> from the <config> with { host: "0.0.0.0", port: 8080, debug: false }.
(* full = { host: "localhost", port: 8080, debug: false } *)
(* Note: host kept its original value *)

extend

Compute the <result: lowbar.extend> from the <object> with { key: value, ... }.

Merges the with properties into the object, overwriting any existing keys. The forceful cousin of defaults.

Compute the <updated: lowbar.extend> from the <config> with { port: 9090, debug: true }.
(* updated = { host: "localhost", port: 9090, debug: true } *)

clone

Compute the <result: lowbar.clone> from the <value>.

Creates a shallow copy of an object or list.

Compute the <copy: lowbar.clone> from the <config>.
(* copy = { host: "localhost" }  (independent copy) *)

has

Compute the <result: lowbar.has> from the <object> with { key: "..." }.

Checks whether an object contains a specific key. Returns a boolean.

Compute the <exists: lowbar.has> from { name: "Alice" } with { key: "name" }.
(* exists = true *)

get

Compute the <result: lowbar.get> from the <object> with { path: "..." }.

Retrieves a value at a nested dot-separated path. Supports an optional default value when the path doesn't resolve.

Create the <data> with { user: { address: { city: "Portland" } } }.

Compute the <city: lowbar.get> from the <data> with { path: "user.address.city" }.
(* city = "Portland" *)

Compute the <phone: lowbar.get> from the <data> with { path: "user.phone", default: "N/A" }.
(* phone = "N/A" *)

find-key

Compute the <result: lowbar.find-key> from the <object> with { value: x }.

Returns the first key whose value matches. The reverse lookup.

Create the <codes> with { red: "#ff0000", green: "#00ff00" }.
Compute the <name: lowbar.find-key> from the <codes> with { value: "#ff0000" }.
(* name = "red" *)

map-object

Compute the <result: lowbar.map-object> from the <object> with { from: "...", to: "..." }.

Renames keys in an object. Use from/to for a single rename, or map for bulk renaming.

Compute the <renamed: lowbar.map-object> from { first_name: "Alice" } with { from: "first_name", to: "name" }.
(* renamed = { name: "Alice" } *)

Compute the <mapped: lowbar.map-object> from { a: 1, b: 2 } with { map: { a: "x", b: "y" } }.
(* mapped = { x: 1, y: 2 } *)

is-match

Compute the <result: lowbar.is-match> from the <object> with { key: value, ... }.

Returns true if the object contains all the given key-value pairs. A subset check for objects.

Compute the <match: lowbar.is-match> from { name: "Alice", role: "admin" } with { role: "admin" }.
(* match = true *)

Type Checks

Inspect the type of any value. Each returns a boolean.

is-empty

Compute the <result: lowbar.is-empty> from the <value>.

Returns true for empty lists, empty strings, empty objects, and nil. Everything else is considered non-empty.

Compute the <a: lowbar.is-empty> from [].
(* a = true *)

Compute the <b: lowbar.is-empty> from "hello".
(* b = false *)

is-array

Compute the <result: lowbar.is-array> from the <value>.

Returns true if the value is a list.

Compute the <check: lowbar.is-array> from [1, 2].
(* check = true *)

is-string

Compute the <result: lowbar.is-string> from the <value>.

Returns true if the value is a string.

Compute the <check: lowbar.is-string> from "hello".
(* check = true *)

is-number

Compute the <result: lowbar.is-number> from the <value>.

Returns true if the value is an integer or floating-point number.

Compute the <check: lowbar.is-number> from 42.
(* check = true *)

is-boolean

Compute the <result: lowbar.is-boolean> from the <value>.

Returns true if the value is a boolean.

Compute the <check: lowbar.is-boolean> from true.
(* check = true *)

is-object

Compute the <result: lowbar.is-object> from the <value>.

Returns true if the value is an object (key-value dictionary).

Compute the <check: lowbar.is-object> from { a: 1 }.
(* check = true *)

is-null

Compute the <result: lowbar.is-null> from the <value>.

Returns true if the value is nil/null.

is-finite

Compute the <result: lowbar.is-finite> from the <number>.

Returns true if the value is a finite number (not infinity or NaN).

Compute the <check: lowbar.is-finite> from 42.
(* check = true *)

is-equal

Compute the <result: lowbar.is-equal> from the <value> with { other: x }.

Deep equality comparison between two values.

Compute the <same: lowbar.is-equal> from 42 with { other: 42 }.
(* same = true *)

Compute the <diff: lowbar.is-equal> from "hello" with { other: "world" }.
(* diff = false *)

Utilities

String manipulation, data conversion, and pipeline helpers.

identity

Compute the <result: lowbar.identity> from the <value>.

Returns the value unchanged. Sounds useless, but it's the default qualifier — a no-op that's occasionally exactly what you need in a pipeline.

Compute the <same: lowbar.identity> from 42.
(* same = 42 *)

escape

Compute the <result: lowbar.escape> from the <string>.

Escapes a string for safe HTML insertion, converting &, <, >, ", and ' to their HTML entity equivalents.

Compute the <safe: lowbar.escape> from "<b>bold & \"italic\"</b>".
(* safe = "&lt;b&gt;bold &amp; &quot;italic&quot;&lt;/b&gt;" *)

unescape

Compute the <result: lowbar.unescape> from the <string>.

The inverse of escape. Converts HTML entities back to their characters.

Compute the <raw: lowbar.unescape> from "&lt;b&gt;bold&lt;/b&gt;".
(* raw = "<b>bold</b>" *)

join

Compute the <result: lowbar.join> from the <list> with { separator: "..." }.

Concatenates all elements into a single string with a separator between each. Defaults to ",".

Compute the <csv: lowbar.join> from ["alice", "bob", "eve"] with { separator: ", " }.
(* csv = "alice, bob, eve" *)

split

Compute the <result: lowbar.split> from the <string> with { separator: "..." }.

Splits a string into a list by a separator. The inverse of join.

Compute the <parts: lowbar.split> from "one:two:three" with { separator: ":" }.
(* parts = ["one", "two", "three"] *)

tap

Compute the <result: lowbar.tap> from the <value>.

Returns the value unchanged — a pass-through useful as a checkpoint in data pipelines or debugging.

Compute the <debug: lowbar.tap> from the <data>.
Log <debug> to the <console>.
(* Logs the data and passes it through *)

Actions

Actions generate new data rather than transforming existing values. They use the Lowbar. prefix (PascalCase) as verb-based statements.

Range

Lowbar.Range the <result> with { stop: N }.

Generates a list of integers from start (default 0) up to but not including stop, incrementing by step (default 1). Automatically counts down when start is greater than stop.

Lowbar.Range the <digits> with { stop: 5 }.
(* digits = [0, 1, 2, 3, 4] *)

Lowbar.Range the <evens> with { start: 0, stop: 10, step: 2 }.
(* evens = [0, 2, 4, 6, 8] *)

Lowbar.Range the <countdown> with { start: 5, stop: 0 }.
(* countdown = [5, 4, 3, 2, 1] *)

Random

Lowbar.Random the <result> with { min: N, max: N }.

Generates a random integer between min and max inclusive. Defaults to 0–100.

Lowbar.Random the <dice> with { min: 1, max: 6 }.
(* dice = 4  (random 1-6) *)

Lowbar.Random the <percent> with { min: 0, max: 100 }.
(* percent = 73  (random 0-100) *)

UniqueId

Lowbar.UniqueId the <result> with { prefix: "..." }.

Generates a globally unique identifier with an optional prefix. Each call produces a new, incrementing ID.

Lowbar.UniqueId the <id1> with { prefix: "user_" }.
Lowbar.UniqueId the <id2> with { prefix: "user_" }.
(* id1 = "user_1" *)
(* id2 = "user_2" *)

Now

Lowbar.Now the <result> for the <system>.

Returns the current Unix timestamp in milliseconds. Useful for timing and date calculations.

Lowbar.Now the <timestamp> for the <system>.
(* timestamp = 1713436800000 *)

Times

Lowbar.Times the <result> with { n: N, value: x }.

Creates a list containing n copies of a value.

Lowbar.Times the <stars> with { n: 5, value: "*" }.
(* stars = ["*", "*", "*", "*", "*"] *)

Lowbar.Times the <zeros> with { n: 3, value: 0 }.
(* zeros = [0, 0, 0] *)