8.1 Lists
Lists can be constructed using the syntax [expr, ...], which creates list containing the values of the exprs as elements. More precisely, a use of square brackets without a preceding expression implicitly uses the #%brackets form, which is normally bound to construct a list.
A list is indexable using […] to access a list
element by position—
Static information associated by List or List.of makes an expression acceptable as a sequence to for in static mode.
function | ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
| ||||||||||||
repetition | ||||||||||||
| ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
| ||||||||||||
repetition | ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
|
The #%brackets form is implicitly used when […] is used in an expression position. See also Implicit Forms.
> lst
[1, 2, 3]
> lst[0]
1
> lst ++ [4, 5]
[1, 2, 3, 4, 5]
> #%brackets [1, 2, 3]
[1, 2, 3]
binding operator | ||||||||||||
| ||||||||||||
| ||||||||||||
binding operator | ||||||||||||
| ||||||||||||
| ||||||||||||
binding operator | ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
|
> y
3
> also_y
3
> xs
[2, 3]
> [x, ...]
[2, 3]
> [x, ...]
[2]
> [x, ...]
[2]
def: value does not satisfy annotation
value: [1, 3]
annotation: matching(List(1, _, ... ~nonempty, 3))
def: value does not satisfy annotation
value: [1, 2, 2, 3]
annotation: matching(List(1, _, ... ~once, 3))
If multiple splices are present, matching is greedy: the first splice matches as many elements as possible to achieve a successful match, and so on for subsequent matches with the remaining elements.
> [[x, ...], [z, ...]]
[[1, 2, "c", 5], []]
> [[x, ...], [z, ...]]
[[1, 2, "c"], [5]]
> [[x, ...], [z, ...]]
[[1, 2, "c"], [5]]
> [[x, ...], y, [z, ...]]
[[1, 2], "c", ["d", 5]]
For a & list_repet_bind , ellipsis splice repetition, list_repet_bind is matched greedily to a non-empty sequence for each repetition of the splice.
> [[x, ...], ...]
[[1, 2, 3, 4]]
> def List(& [x :: Int, ..., y], ..., z, ...) = [1, 2, "c", 4, "e", 6]
> [[[x, ...], ...], [y, ...], [z, ...]]
[[[1, 2], [4], []], ["c", "e", 6], []]
When splice does not impose a predicate or conversion on a matching value (e.g., repet_bind or list_bind is an identifier), then the corresponding elements of a matching value are not traversed, which means that matching takes only the time needed by List.sublist (practically constant time) for a single such splice. Using this repetition in a new list similarly avoids traversing the elements.
A splice of the form & list_bind may have a statically known length. In particular, static information with the key statinfo_meta.list_bounds_key is associated with the overall pattern, so if list_bind is based on a list pattern, it may report its bounds via that key. The list matcher will not attempt to matches that are inconsistent with known bounds, and a multi-splice pattern using & list_bind splices is potentially deterministic and efficient if bounds can be determined statically. The same is true for list_repet_bind in a splice repetition, but the list matcher can only recompute expected bounds for a list size, not an expected modulus for a list size.
When multiple splices are present, the search for a match to each repet_bind , ellipsis splice first builds up a candidate sequence as long as possible by stopping when an element doesn’t satisfy repet_bind, and then the matcher backtracks to shorter sequences as needed to find an overall match. The search for a match to & list_bind tries first matching the longest plausible sequence to list_bind, then backtracks as needed by trying smaller sequences. Matching a splice repetition combines these strategies: search uses the longer plausible candidiate for a given repetition, and it builds up repetitions until no (non-empty) match is found for a repetition.
In the case of a & list_bind splice or & list_repet_bind , ellipsis splice repetition, static information associated by List is propagated to list_bind or list_repet_bind.
The #%brackets form is implicitly used when […] is used in a binding position. See also Implicit Forms.
annotation | |
| |
annotation | |
> [1] :: NonemptyList
[1]
> [] :: NonemptyList
::: value does not satisfy annotation
value: []
annotation: NonemptyList
reducer | |
> List.insert(["a", "b", "c"], 1, "x")
["a", "x", "b", "c"]
> List.add([2, 3], 1)
[2, 3, 1]
[2, 3, 1]
> block:
[2, 3, 1]
> List.cons(1, [2, 3])
[1, 2, 3]
[1, 2, 3]
> x
1
> y
[2, 3]
value | |
| |
| |
binding operator | |
"b"
> ["a", "b", "c"][1]
"b"
property | |
|
> List.first(["a", "b", "c"])
"a"
"a"
> List.last(["a", "b", "c"])
"c"
"c"
> List.rest(["a", "b", "c"])
["b", "c"]
["b", "c"]
> List.delete(["a", "b", "c"], 1)
["a", "c"]
["a", "beta", "c"]
["a", "beta", "c"]
3
0
[8, 4, 1]
method | |
| |
function | |
[1, 2, 3, 4, 5, 6]
> List.append([1, 2, 3], [4, 5], [6])
[1, 2, 3, 4, 5, 6]
> List.append()
[]
method | |
| |
method | |
[1, 2]
[4, 5]
List.take: index is out of range
index: 2
valid range: [0, 1]
list: [1]
method | |
| |
method | |
[3, 4, 5]
[1, 2, 3]
List.drop: index is out of range
index: 2
valid range: [0, 1]
list: [1]
[2, 3]
[2, 3]
method | |||
> [1, 2, 3].has_element(2)
#true
> [1, 2, 3].has_element(200)
#false
method | ||
| ||
method | ||
2
#false
1
#false
[1, 3, 2]
method | ||
| ||
method | ||
[2, 3, 4]
[2, 3, 4]
1
2
3
method | ||||
| ||||
| ||||
method | ||||
|
The List.partition function returns two lists that are like lst, but with complementary elements: the first result list has elements for which pred returns a true value, and the second result list has elements for which pred returns #false.
[1, 2]
[-1, -2]
[-1]
[1, 2]
[-1, -2]
> List.sort([1, 3, 2])
[1, 2, 3]
[3, 2, 1]
> List.iota(3)
[0, 1, 2]
> List.iota(0)
[]
MutableList[1, 2, 3]
repetition | |
> block:
[x+1, ...]
[2, 3, 4]
> [List.repet(lst) + 1, ...]
[2, 3, 4]