Collections & Iteration
Lists
The workhorse collection is List, written with square brackets. Elements can be anything, and needn't share a type:
xs = [1, "foo", []]
Indexing is 1-based, with the usual bracket syntax:
xs[2] # "foo"
xs[2] = 10 # update (creates a new value, as ever)
The core operations:
length(xs)
append(&xs, 4) # add to the end
pop(&xs) # remove from the end, returning it
empty?(xs)
Remember that lists are values: append(&ys, 4) changes the variable ys and nothing else.
Ranges
range(a, b) is an iterable range, inclusive at both ends:
for i = range(1, 10) { println(i) }
collect(range(1, 5)) # [1, 2, 3, 4, 5]
map, collect, reduce
The functional staples are here:
fn twice(x) { x * 2 }
collect(map(range(1, 3), twice)) # [2, 4, 6]
reduce(range(1, 4), +) # 10
sum(xs)
map is lazy – it produces a Mapping you can iterate; collect realises any iterable into a list. Note there's no lambda syntax yet, so map takes named functions.
Sequences
The standard library also has Sequence, an immutable linked list in the Lisp tradition, built from prepend cells:
s = seq(1, 2, 3)
first(s) # 1
rest(s) # seq(2, 3)
prepend(s, 0)
Lists are better for indexing and appending; sequences for sharing structure and recursion.
The iteration protocol
for loops, map, collect and friends work on anything iterable. The protocol is two functions:
iterate(xs)returns an iterator value.next(&itr)returnsSome(value)and advances the iterator, ornilwhen exhausted.
Any type can join by extending them:
bundle Countdown(n)
@extend
fn iterate(c: Countdown) { c }
@extend
fn next(&c: Countdown(n)) {
if n == 0 { return nil }
c = Countdown(n - 1)
return Some(n)
}
collect(Countdown(3)) # [3, 2, 1]
For simple indexable collections, IndexIterator(xs) gives you iteration for free once length and indexing are defined.
What's missing
There are no hash maps or sets yet – it's the standard library's most obvious gap, and high on the roadmap. For small key/value needs, records can stand in.