DOCUMENTATION

Collections

DOCUMENTATION

XCX 4.4.1 Collections

Arrays

$ xcx
_ ⛶ ×
1array:i: nums {10, 20, 30};
2nums.size(); --- 3
3nums.get(0); --- 10
4nums.push(40); --- adds 40 to the end
5i: last = nums.pop(); --- removes and returns last element
6nums.sort(); --- sorts in-place
7nums.reverse(); --- reverses in-place
8nums.show(); --- prints contents to terminal

Array Methods

MethodSignatureReturnsDescription
.size()() → iiNumber of elements (aliases: .count(), .len())
.count()() → iiNumber of elements (alias of .size())
.get(i)(i) → TTElement at position i (0-indexed); halt.error if out of bounds
.push(val)(T) → bbAppends element to the end
.pop()() → TTRemoves and returns the last element
.insert(i, val)(i, T) → bbInserts at position i, shifts rest; halt.error if out of bounds
.update(i, val)(i, T) → bbOverwrites element at position i; halt.error if out of bounds
.delete(i)(i) → bbRemoves element at position i; halt.error if out of bounds
.find(val)(T) → iiIndex of first occurrence, or -1
.contains(val)(T) → bbChecks if value exists
.isEmpty()() → bbtrue if empty
.clear()() → bbRemoves all elements
.sort()() → bbSorts ascending (in-place)
.reverse()() → bbReverses order (in-place)
.slice(s, e)(i, i) → array:Tarray:TReturns a sub-array from index s up to e
.toStr()() → ssSerializes array to a JSON-formatted string
.toJson()() → jsonjsonConverts array to a native JSON structure
.show()() → bbPrints contents to terminal
$ xcx
_ ⛶ ×
1array:i: nums {5, 2, 8, 1};
2nums.sort(); --- {1, 2, 5, 8}
3nums.reverse(); --- {8, 5, 2, 1}
4nums.push(99); --- {8, 5, 2, 1, 99}
5i: last = nums.pop(); --- last = 99, nums = {8, 5, 2, 1}
6nums.insert(1, 15); --- inserts 15 at position 1
7nums.update(0, 5); --- sets element 0 to 5
8nums.delete(3); --- removes element at position 3
9b: found = nums.contains(5);
10i: idx = nums.find(5);
11b: empty = nums.isEmpty();

Sets

Domains

SymbolTypeExample
NNatural (≥ 0)set:N: s {0, 1, 2}
ZIntegerset:Z: s {-3, 0, 3}
QRational (Float)set:Q: s {0.5, 1.0}
SStringset:S: s {"a", "b"}
BBooleanset:B: s {true, false}
CCharacterset:C: s {"A",,"Z"}

Initialization

Sets can be initialized with explicit values or ranges. Ranges are inclusive on both sides.

$ xcx
_ ⛶ ×
1set:N: small {1,,5}; --- {1, 2, 3, 4, 5}
2set:N: evens {0,,100 @step 2}; --- {0, 2, 4, ...}
3set:Q: thirds {0.0,,1.0 @step 0.33};
4set:C: letters {"A",,"Z"}; --- all uppercase letters

Sets automatically deduplicate elements.

Set Operations

$ xcx
_ ⛶ ×
1set:N: setA {1,,5};
2set:N: setB {3,,7};
3
4set:N: u = setA UNION setB;
5set:N: i = setA INTERSECTION setB;
6set:N: d = setA DIFFERENCE setB;
7set:N: sd = setA SYMMETRIC_DIFFERENCE setB;
8
9--- Unicode symbols are equivalent
10setA ∪ setB
11setA ∩ setB
12setA \ setB
13setA ⊕ setB

Set Methods

MethodSignatureReturnsDescription
.size()() → iiNumber of elements (aliases: .count(), .len())
.count()() → iiNumber of elements (alias of .size())
.isEmpty()() → bbtrue if empty
.contains(v)(T) → bbChecks membership
.add(v)(T) → bbAdds element (ignores duplicate)
.remove(v)(T) → bbRemoves element (no-op if not present)
.clear()() → bbRemoves all elements
.show()() → bbPrints {elem, elem, ...} to terminal

Random Selection and Iteration

$ xcx
_ ⛶ ×
1--- Random selection from a set:
2i: picked_set = random.choice from small;
3
4--- Random selection from an array:
5array:i: nums {1, 2, 3, 4, 5};
6i: picked_arr = random.choice from nums;

Picking from an empty set or array returns false.

Iteration

$ xcx
_ ⛶ ×
1for p in small do;
2 >! p;
3end;

Maps

$ xcx
_ ⛶ ×
1map: ages {
2 schema = [s <-> i]
3 data = [ "alice" :: 30, "bob" :: 25 ]
4};
5
6--- Empty Map
7map: scores {
8 schema = [s <-> i] --- both separators are equivalent (<-> and <=>)
9 data = [EMPTY]
10};

WARNING:

Path-like keys - behavior will change in XCX 5.0a; do not build on it.

A string key that contains ., contains [, or starts with / is not

stored as a literal key: get / set / insert / contains / remove

interpret it as a nested path (e.g. "a.b" targets key "b" inside the

map nested under "a"), and size() counts only top-level entries.

Consequence: URLs, dotted identifiers, and any key containing those

characters cannot be used as literal keys. Until 5.0, key such values by

a safe slug or id and keep the original string as the stored value.

Map Methods

MethodSignatureReturnsDescription
.size()() → iiNumber of key-value pairs (aliases: .count(), .len())
.count()() → iiNumber of key-value pairs (alias of .size())
.get(key)(K) → VVReturns value; halt.error if key missing
.contains(key)(K) → bbChecks if key exists
.insert(k, v)(K, V) → bbInserts or overwrites
.remove(key)(K) → bbRemoves pair; false if key missing
.keys()() → array:Karray:KReturns array of keys
.values()() → array:Varray:VReturns array of values
.clear()() → bbRemoves all pairs
.toStr()() → ssSerializes map to a JSON-formatted string
.show()() → bbPrints map contents to terminal
.toJson()() → jsonjsonSerializes map to a JSON object

Map keys are converted to strings in the resulting JSON object.

Map Serialization (toJson)

#### Signature

.toJson() → json

#### Description

Serializes the map to a JSON object. All keys are converted to strings using their .toString() representation to satisfy JSON object key requirements.

$ xcx
_ ⛶ ×
1map: scores {
2 schema = [s <-> i]
3 data = [ "alice" :: 100, "bob" :: 85 ]
4};
5json: j = scores.toJson();

JSON Output:

$ json
_ ⛶ ×
1{
2 "alice": 100,
3 "bob": 85
4}

#### Behavior for Special Cases

  • Empty Map: Returns an empty object {}.
  • Nested Structures: If a map contains arrays, other maps, or tables, they are recursively serialized to their JSON equivalents.
  • Key Conversion: All map keys are converted to strings in the resulting JSON object using their standard .toString() representation.

#### Type Mapping

XCX TypeJSON Type
inumber
fnumber
sstring
bboolean
datestring (format "YYYY-MM-DD HH:mm:ss")
json(unchanged)

Always use .contains() before .get():

$ xcx
_ ⛶ ×
1if (ages.contains("alice")) then;
2 >! ages.get("alice");
3end;

Tables

Relational data structures with optional auto-increment columns.

NOTE:

Semicolons after blocks are optional (recommended style: without). The

; after the closing } of { }-shaped declarations - array/set

literals, map, table, database - may be omitted and is removed in

XCX 5.0a.

$ xcx
_ ⛶ ×
1table: products {
2 columns = [ id :: i @auto, name :: s, price :: f ]
3 rows = [ ("Laptop", 2999.99), ("Phone", 1499.50) ]
4};
5
6--- Empty Table
7table: logs {
8 columns = [ id :: i @auto, msg :: s ]
9 rows = [EMPTY]
10};

The @auto modifier on an i column creates an auto-incremented ID - it is skipped in .insert() and .add().

NOTE:

Additional column attributes (@pk, @unique, @optional, @default(v), @fk(t.col)) are used when connecting a table to a database. See Database Documentation for details.

Row Access

$ xcx
_ ⛶ ×
1products[0].name --- "Laptop" (sugar for .get(0))
2products[1].price --- 1499.50

Table Methods

MethodSignatureReturnsDescription
.count()() → iiNumber of rows (aliases: .size(), .len())
.get(i)(i) → rowrowRow at index i
.insert(vals...)(T...) → bbAdds row (skips @auto columns)
.add(vals...)(T...) → bbAlias for .insert() - identical behavior
.update(i, vals)(i, [T...]) → bbReplaces row values; @auto columns preserved
.delete(i)(i) → bbRemoves row at index i
.where(pred)(expr) → tabletableFilters - returns a new table
.join(t, pred)(table, pred) → tabletableInner join with another table
.toJson()() → jsonjsonSerializes all rows to a JSON array of objects
.show()() → bbPrints table in ASCII format

Named Arguments for .add() and .insert()

When a table has database column attributes, values can be passed by column name instead of position. Named arguments are optional - positional calls remain fully valid.

$ xcx
_ ⛶ ×
1table: users {
2 columns = [
3 id :: i @auto @pk,
4 name :: s @unique,
5 age :: i,
6 phone :: s @optional,
7 role :: s @default("user")
8 ]
9 rows = [EMPTY]
10};
11
12--- Positional (backward compatible)
13users.add("Alice", 25, "", "user");
14
15--- Named
16users.add(name = "Alice", age = 25, phone = "", role = "user");
17
18--- Mixed - positional args must come first
19users.add("Alice", age = 25, role = "admin");

Namespace separation. The left side of = is always the column name. The right side is an expression from the local scope. These are two independent namespaces - no conflict:

$ xcx
_ ⛶ ×
1s: name = "Alice";
2users.add(name = name, age = 25);
3--- left "name" = column users.name
4--- right "name" = local variable

Rules: positional args must precede named; @auto columns can never be passed; omitting a required (non-@optional, non-@default) column is a compile error; duplicate column names in the same call are a compile error. See Database Documentation for the full specification.

Filtering (where)

$ xcx
_ ⛶ ×
1--- Shorthand syntax (column names usable directly)
2table: expensive = products.where(price > 1000.0);
3table: named = products.where(name HAS "Pro");
4
5--- Lambda
6table: r = products.where(row -> row.price > 1000.0);
7
8--- Chaining
9table: result = products
10 .where(price > 1000.0)
11 .where(name HAS "Pro");

IMPORTANT:

Name Conflicts in .where() (S301): Column names take precedence over local variables inside predicates. If a local variable has the same name as a column, rename the variable to avoid a compile error.

$ xcx
_ ⛶ ×
1--- Wrong (conflict: 'token' exists both as column and parameter)
2fiber verify(s: token) {
3 table: sess = db.sessions.where(token == token);
4};
5
6--- Correct
7fiber verify(s: t) {
8 table: sess = db.sessions.where(token == t);
9};

Joins

$ xcx
_ ⛶ ×
1--- Key-based join
2table: report = users.join(orders, "id", "user_id");
3
4--- Lambda join
5table: custom = tableA.join(tableB, (a, b) -> a.id == b.ref_id);

When joined tables share a column name (other than the join key), the resulting column is prefixed with {table_name}_.

Serialization (toJson)

#### Signature

.toJson() → json

#### Description

Serializes all rows of a table to a JSON array, where each row becomes an object with keys corresponding to column names. @auto columns are included in the result.

#### Format

Always returns a JSON array ([...]). An empty table returns [].

$ xcx
_ ⛶ ×
1table: products {
2 columns = [ id :: i @auto, name :: s, price :: f ]
3 rows = [ ("Laptop", 2999.99), ("Phone", 1499.50) ]
4};
5
6json: result = products.toJson();

JSON Output:

$ json
_ ⛶ ×
1[
2 {"id": 1, "name": "Laptop", "price": 2999.99},
3 {"id": 2, "name": "Phone", "price": 1499.50}
4]

#### Type Mapping

XCX TypeJSON Type
i / intnumber
f / floatnumber
s / strstring
b / boolboolean
datestring (format "YYYY-MM-DD HH:mm:ss")

#### Behavior for Special Cases

  • Empty Table: Returns an empty array [].
  • Filtered Table: Only rows currently in the table (after .where()) are serialized.
  • Joined Table: All columns from the joined result are included.