Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Collections

Collection builtins are the backbone of AetherShell’s pipeline-oriented design. They operate on Arrays, Records, and Tables, returning structured data for further processing.

Transforming

map

Apply a function to each element in an array, returning a new array.

[1, 2, 3] | map(fn(x) => x * 2)
# [2, 4, 6]

# With records
ls "." | map(fn(f) => { name: f.name, kb: f.size / 1024 })

each

Like map but intended for side effects. Returns the original array unchanged.

[1, 2, 3] | each(fn(x) => print "${x} ")
# Prints: 1 2 3
# Returns: [1, 2, 3]

Filtering

where

Keep only elements that satisfy a predicate.

[1, 2, 3, 4, 5] | where(fn(x) => x > 3)
# [4, 5]

ls "." | where(fn(f) => f.extension == "rs")

any

Return true if at least one element satisfies the predicate.

[1, 2, 3] | any(fn(x) => x > 2)   # true
[1, 2, 3] | any(fn(x) => x > 5)   # false

all

Return true if every element satisfies the predicate.

[2, 4, 6] | all(fn(x) => x % 2 == 0)   # true
[2, 4, 5] | all(fn(x) => x % 2 == 0)   # false

Reducing

reduce

Fold an array down to a single value with an accumulator.

[1, 2, 3, 4] | reduce(fn(acc, x) => acc + x, 0)
# 10

# Build a record from an array
["a", "b", "c"] | reduce(fn(acc, x) => { ...acc, [x]: true }, {})
# { a: true, b: true, c: true }

sum

Sum all numeric elements.

[1, 2, 3, 4] | sum        # 10
ls "." | map(fn(f) => f.size) | sum

avg / mean

Compute the arithmetic mean.

[10, 20, 30] | avg         # 20.0

product

Multiply all elements together.

[2, 3, 4] | product        # 24

min / max

Return the minimum or maximum value.

[3, 1, 4, 1, 5] | min      # 1
[3, 1, 4, 1, 5] | max      # 5

Selecting

first

Return the first element of an array.

[10, 20, 30] | first        # 10

last

Return the last element of an array.

[10, 20, 30] | last         # 30

take

Return the first N elements.

[1, 2, 3, 4, 5] | take 3   # [1, 2, 3]

slice

Extract a sub-array by start index and length.

[10, 20, 30, 40, 50] | slice 1 3
# [20, 30, 40]

Ordering

sort_by

Sort an array of records by a field, with optional direction.

ls "." | sort_by "size" "desc" | take 5
# Top 5 largest files

let people = [
  { name: "Charlie", age: 30 },
  { name: "Alice", age: 25 },
  { name: "Bob", age: 28 }
]
people | sort_by "name" "asc"

reverse

Reverse the order of elements.

[1, 2, 3] | reverse        # [3, 2, 1]

Combining

push

Append an element to an array.

[1, 2, 3] | push 4         # [1, 2, 3, 4]

concat

Concatenate two arrays.

concat [1, 2] [3, 4]       # [1, 2, 3, 4]

zip

Combine two arrays into an array of pairs.

zip ["a", "b", "c"] [1, 2, 3]
# [["a", 1], ["b", 2], ["c", 3]]

flatten

Flatten nested arrays by one level.

[[1, 2], [3, 4], [5]] | flatten
# [1, 2, 3, 4, 5]

Uniqueness

unique

Remove duplicate values from an array.

[1, 2, 2, 3, 3, 3] | unique    # [1, 2, 3]

Generators

range

Generate a sequence of integers.

range 1 5         # [1, 2, 3, 4]
range 0 10 2      # [0, 2, 4, 6, 8]  (with step)

Record Operations

keys

Return the keys of a record as an array.

keys { x: 1, y: 2, z: 3 }     # ["x", "y", "z"]

values

Return the values of a record as an array.

values { x: 1, y: 2, z: 3 }   # [1, 2, 3]

Size

len / length

Return the number of elements in an array, characters in a string, or keys in a record.

len [1, 2, 3]       # 3
len "hello"          # 5
len { a: 1, b: 2 }  # 2

Membership

in

Test if a value is in an array or a key is in a record.

3 in [1, 2, 3]                # true
"name" in { name: "Ada" }     # true

Pipeline Composition

Collections compose naturally through the pipe operator:

# Data analysis pipeline
ls "src"
  | where(fn(f) => f.extension == "rs")
  | map(fn(f) => { name: f.name, lines: len(split(cat(f.path), "\n")) })
  | sort_by "lines" "desc"
  | take 5

# Aggregation
range 1 100
  | where(fn(x) => x % 3 == 0 || x % 5 == 0)
  | sum
# 2318

# Nested transformation
[
  { dept: "eng", people: ["Alice", "Bob"] },
  { dept: "hr", people: ["Charlie"] }
]
  | map(fn(d) => d.people | map(fn(p) => { name: p, dept: d.dept }))
  | flatten