8.3 Mutable Lists
A mutable list is a mutable object that contains a list. A mutable list is not by itself a list (i.e., it will not satisfy the List annotation), but it is listable.
A mutable list is indexable using […] to access a list
element by position—
Operations on a mutable list tend to modify the mutable list and produce #void, instead of creating a new list or returning the modified mutable list.
The model of a mutable list as an object containing a list explains its behavior in the case of concurrent modification: concurrent element assignments for different positions will not interfere, but races with other operations will sometimes negate one of the modifications. Concurrent modification is thus somewhat unpredictable but still safe, and it is not managed by a lock.
annotation | |
| |
annotation | |
| |
annotation | |
The MutableList.now_of form constructs a predicate annotation that matches a mutable list whose elements all currently satisfy annot, but it does not ensure in any way that future values installed into the mutable list will satisfy annot. The given annot must not be a converting annotation. Static information from annot is not propagated to accesses of the mutable list, since there’s no guarantee that the value will still satisfy the annotation.
The MutableList.later_of form constructs a converter annotation that immediately matches a mutable list without checking that its elements currently satisfy annot. The conversion result of the annotation is a view of the original mutable list, but one where annot is checked against a value that would be returned by accessing an element of the mutable list or a value to be installed into the mutable list. (A different view of the mutable list might change an element to one that does not satisfy annot.) Static information from annot is propagated to accesses of the mutable list. Note that a converter annot is applied for each access or update.
Static information associated by MutableList or MutableList.now_of makes an expression acceptable as a sequence to for in static mode.
> MutableList(1, 2, 3) :: MutableList
MutableList[1, 2, 3]
> MutableList(1, 2, 3) :: MutableList.now_of(Number)
MutableList[1, 2, 3]
> MutableList(1, "b", 3) :: MutableList.now_of(Number)
::: value does not satisfy annotation
value: MutableList[1, "b", 3]
annotation: MutableList.now_of(Number)
def l :: MutableList.later_of(Number) = MutableList(1, "b", 3)
> l[0]
1
> l[1]
MutableList: current element does not satisfy annotation
current element: "b"
position: 1
annotation: Number
> l[2] := "c"
MutableList: new element does not satisfy annotation
new element: "c"
position: 2
annotation: Number
function | ||||||||||||
| ||||||||||||
| ||||||||||||
expression | ||||||||||||
| ||||||||||||
| ||||||||||||
repetition | ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
| ||||||||||||
|
> def l = MutableList(1, 2, 3)
> l
MutableList[1, 2, 3]
> l[0]
1
> l[0] := 10
> l
MutableList[10, 2, 3]
> MutableList.snapshot(l)
[10, 2, 3]
> def l = MutableList["a", "b", "c"]
> MutableList.insert(l, 1, "x")
> l
MutableList["a", "x", "b", "c"]
> def l = MutableList[2, 3]
> MutableList.add(l, 1)
> l
MutableList[2, 3, 1]
> l
MutableList[2, 3, 1, 0]
> l
MutableList[2, 3, 1, 0, 10]
function | |
|
> def l = MutableList[2, 3]
> MutableList.cons(1, l)
> l
MutableList[1, 2, 3]
> MutableList["a", "b", "c"].get(1)
"b"
> MutableList["a", "b", "c"][1]
"b"
> def l = MutableList["a", "b", "c"]
> l
MutableList["a", "beta", "c"]
> l[2] := "gamma"
> l
MutableList["a", "beta", "gamma"]
> def l = MutableList["a", "b", "c"]
> MutableList.delete(l, 1)
> l
MutableList["a", "c"]
> MutableList[1, 4, 8].length()
3
> MutableList[].length()
0
> def l = MutableList[1, 4, 8]
> l
MutableList[8, 4, 1]
> def l = MutableList[1, 2, 3]
> MutableList.append(l, [4, 5])
> MutableList.append(l, MutableList[6])
> l
MutableList[1, 2, 3, 4, 5, 6]
method | ||
| ||
method | ||
> def l = MutableList[1, 2, 3, 4, 5]
> l
MutableList[1, 2, 3]
> l
MutableList[2, 3]
MutableList.take: index is out of range
index: 10
valid range: [0, 2]
mutable list: MutableList[2, 3]
method | ||
| ||
method | ||
> def l = MutableList[1, 2, 3, 4, 5]
> l
MutableList[3, 4, 5]
> l
MutableList[3, 4]
MutableList.drop: index is out of range
index: 10
valid range: [0, 2]
mutable list: MutableList[3, 4]
method | |||
| |||
method | |||
When given one argument, rge is used to derive start and end as in String.substring.
> def l = MutableList[1, 2, 3, 4, 5]
> l
MutableList[2, 3]
method | |||
> def l = MutableList[1, 2, 3]
#true
#false
#true
> 2 in l
#true
method | |||
> def l = MutableList["a", "b", "c"]
1
#false
> l.index("B", fun (a, b): Char.downcase(a[0]) == Char.downcase(b[0]))
1
method | ||
| ||
| ||
method | ||
|
> def l = MutableList[1, 2, 3]
2
#false
> l.find_index((_ mod 2 .= 0))
1
> l.find_index((_ mod 10 .= 9))
#false
> def l = MutableList[1, 2, 3, 2]
method | ||
| ||
| ||
method | ||
|
> def l = MutableList[1, 2, 3]
> MutableList.map(l, (_ + 1))
> l
MutableList[2, 3, 4]
2
3
4
method | ||||
|
> def l = MutableList[1, 3, 2]
> MutableList.sort(l)
> l
MutableList[1, 2, 3]
> MutableList.sort(l, (_ > _))
> l
MutableList[3, 2, 1]
method | |
|
> MutableList[1, 2, 3].copy()
MutableList[1, 2, 3]
method | |
| |
method | |
method | |
|