std.seq
std.seq holds sequence helpers — ranges, chunking, enumeration, and set
operations. They complement std.sort (which focuses on ordering and
transforming) with tools for generating and slicing sequences.
Many std.seq functions are also available as pipes on arrays — e.g.
arr:take(2), arr:chunk(2) — see Pipes.
Reference
range(end) # [0, 1, ..., end-1]
range(start, end[, step]) # half-open interval
enumerate(array) # [{index, value}, ...]
chunk(array, size) # array of sub-arrays
take(array, n) # first n elements
drop(array, n) # everything after the first n
set_union(a, b)
set_intersect(a, b)
set_difference(a, b) # elements of a not in b
range
range is the idiomatic loop counter (and supports negative steps):
for (i : std.seq.range(5)) { print(i) } # 0 1 2 3 4
print(std.seq.range(1, 6)) # [1, 2, 3, 4, 5]
print(std.seq.range(0, 10, 2)) # [0, 2, 4, 6, 8]
print(std.seq.range(5, 0, -1)) # [5, 4, 3, 2, 1]
Pipe form on an array is not needed — range generates a new array. Use it
wherever you need indices or a counted loop.
Chunking and enumeration
Chunking and enumeration drive paging and index-aware loops:
var rows = std.seq.chunk([1, 2, 3, 4, 5], 2) # [[1, 2], [3, 4], [5]]
var firstTwo = std.seq.take([7, 8, 9], 2) # [7, 8]
var rest = std.seq.drop([7, 8, 9], 2) # [9]
for (p : std.seq.enumerate(["a", "b", "c"])) {
print(p.index, p.value) # 0 a, 1 b, 2 c
}
Pipe equivalents write back into the receiver, so use a fresh array per
call (chaining would feed each result into the next):
var a = [1, 2, 3, 4, 5]
var t = a:take(2) # [1, 2] (a itself is now [1, 2])
var b = [1, 2, 3, 4, 5]
var d = b:drop(2) # [3, 4, 5]
var c = [1, 2, 3, 4, 5]
var h = c:chunk(2) # [[1, 2], [3, 4], [5]]
Set operations
Set operations treat elements as distinct by their string representation and
preserve input order:
std.seq.set_union([1, 2, 3], [2, 3, 4]) # [1, 2, 3, 4]
std.seq.set_intersect([1, 2, 3, 4], [2, 3]) # [2, 3]
std.seq.set_difference([1, 2, 3, 4], [2, 3]) # [1, 4]
Also available as pipes: a:set_union(b), etc.