On this page:
Mutable  List
Mutable  List.now_  of
Mutable  List.later_  of
Mutable  List
Mutable  List
Mutable  List.insert
Mutable  List.add
Mutable  List.cons
Mutable  List.get
Mutable  List.set
Mutable  List.delete
Mutable  List.length
Mutable  List.reverse
Mutable  List.append
Mutable  List.take
Mutable  List.take_  last
Mutable  List.drop
Mutable  List.drop_  last
Mutable  List.sublist
Mutable  List.contains
Mutable  List.index
Mutable  List.find
Mutable  List.find_  index
Mutable  List.remove
Mutable  List.map
Mutable  List.for_  each
Mutable  List.filter
Mutable  List.sort
Mutable  List.copy
Mutable  List.to_  list
Mutable  List.snapshot
Mutable  List.to_  sequence
8.16.0.2

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—in O(log N) time—via #%index, and it also supports element assignment via [] and :=. A mutable list supports membership tests using the in operator. A mutable list can be used as sequence, in which case it supplies its elements in order.

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.

Matches any mutable list in the form without now_of or later_of.

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)

> 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

fun MutableList(v :: Any, ...) :: MutableList

 

expression

MutableList[expr_or_splice, ...]

 

repetition

MutableList[repet_or_splice, ...]

 

expr_or_splice

 = 

expr

 | 

repet , ellipses

 | 

& listable_expr

 

ellipses

 = 

ellipsis

 | 

ellipses , ellipsis

 

ellipsis

 = 

...

Constructs a mutable list of the given vs values or results of the expr_or_splices. A & or ... form can appear within [] to splice a repetition or existing listable value into the constructed list, the same as in a function call (see #%call). Mutable-list constructions can also serve as repetitions, where repet_or_splice is like expr_or_splice, but with repetitions in place of expressions.

> 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]

method

method (mlst :: MutableList).insert(n :: NonnegInt, elem :: Any)

  :: Void

Modifies mlst to add elem before the nth element or at the end if n is the length of lst. The n index must be no more than the length of lst. Insertion takes O(log N) time.

> def l = MutableList["a", "b", "c"]

> MutableList.insert(l, 1, "x")

> l

MutableList["a", "x", "b", "c"]

method

method (mlst :: MutableList).add(elem :: Any) :: Void

Modifies mlst to add elem to the end, equivalent to mlst.insert(mlst.length(), elem).

> def l = MutableList[2, 3]

> MutableList.add(l, 1)

> l

MutableList[2, 3, 1]

> l.add(0)

> l

MutableList[2, 3, 1, 0]

> l.insert(l.length(), 10)

> l

MutableList[2, 3, 1, 0, 10]

function

fun MutableList.cons(elem :: Any, mlst :: MutableList) :: Void

Modifies mlst to add elem before all current elements, equivalent to mlst.insert(0, elem).

> def l = MutableList[2, 3]

> MutableList.cons(1, l)

> l

MutableList[1, 2, 3]

method

method (mlst :: MutableList).get(n :: NonnegInt) :: Any

Equivalent to mlst[n] (with the default implicit #%index form). Returns the nth element of mlst (starting from 0). Accessing a list element by position takes O(log N) time.

> MutableList["a", "b", "c"].get(1)

"b"

> MutableList["a", "b", "c"][1]

"b"

method

method (mlst :: MutableList).set(n :: NonnegInt, v :: Any)

  :: Void

Equivalent to mlst[n] := v (with the default implicit #%index form). Modifies mlst to replace the nth element with v. The n index must be no more than the length of lst. Setting an element takes O(log N) time.

> def l = MutableList["a", "b", "c"]

> l.set(1, "beta")

> l

MutableList["a", "beta", "c"]

> l[2] := "gamma"

> l

MutableList["a", "beta", "gamma"]

method

method (mlst :: MutableList).delete(n :: NonnegInt)

  :: Void

Modifies mlst to delete the nth element. The n index must be less than the length of mlst. Deletion takes O(log N) time.

> def l = MutableList["a", "b", "c"]

> MutableList.delete(l, 1)

> l

MutableList["a", "c"]

Returns the number of items in mlst. The length is produced in O(1) time.

> MutableList[1, 4, 8].length()

3

> MutableList[].length()

0

method

method (mlst :: MutableList).reverse() :: Void

Modifies mlst to have the same elements but in reversed order. Reversing a list takes O(N log N) time, equivalent asymptotically to adding each element of mlst to another list one at a time.

> def l = MutableList[1, 4, 8]

> l.reverse()

> l

MutableList[8, 4, 1]

method

method (mlst :: MutableList).append(lst :: List || MutableList)

  :: Void

Modifies (mslt) to addend the elements of lst in order. Appending N elements takes O(N) time.

> 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 (mlst :: MutableList).take(n :: NonnegInt)

  :: Void

 

method

method (mlst :: MutableList).take_last(n :: NonnegInt)

  :: Void

Modifies mlst to keep only the first n elements in the case of MutableList.take, or only the last n elements in the case of MutableList.take_last. The given mlst must have at least n elements, otherwise an Exn.Fail.Contract exception is thrown. Modifying the list takes O(log N) time, which is asymptotically faster than building a new list by adding or removing elements one at a time.

> def l = MutableList[1, 2, 3, 4, 5]

> l.take(3)

> l

MutableList[1, 2, 3]

> l.take_last(2)

> l

MutableList[2, 3]

> l.take(10)

MutableList.take: index is out of range

  index: 10

  valid range: [0, 2]

  mutable list: MutableList[2, 3]

method

method (mlst :: MutableList).drop(n :: NonnegInt)

  :: Void

 

method

method (mlst :: MutableList).drop_last(n :: NonnegInt)

  :: Void

Modifies mlst to remove the first n elements in the case of MutableList.drop, or the last n elements in the case of MutableList.drop_last. The given mlst must have at least n elements, otherwise an Exn.Fail.Contract exception is thrown. Modifying the list takes O(log N) time, which is asymptotically faster than building a new list by adding or removing elements one at a time.

> def l = MutableList[1, 2, 3, 4, 5]

> l.drop(2)

> l

MutableList[3, 4, 5]

> l.drop_last(1)

> l

MutableList[3, 4]

> l.drop(10)

MutableList.drop: index is out of range

  index: 10

  valid range: [0, 2]

  mutable list: MutableList[3, 4]

method

method (mlst :: MutableList).sublist(rge :: Range)

  :: Void

 

method

method (mlst :: MutableList).sublist(start :: NonnegInt,

                                     end :: NonnegInt)

  :: Void

When given two arguments, modifies mlst to keep only elements from index start (inclusive) to end (exclusive), equivalent to mlst.drop(start) followed by mlst.take(end - start).

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.sublist(1, 3)

> l

MutableList[2, 3]

> def l = MutableList[1, 2, 3, 4, 5]

> l.drop(1)

> l.take(3-1)

> l

MutableList[2, 3]

> def l = MutableList[1, 2, 3, 4, 5]

> l.sublist(1..=3)

> l

MutableList[2, 3, 4]

> def l = MutableList[1, 2, 3, 4, 5]

> l.sublist(1..)

> l

MutableList[2, 3, 4, 5]

> def l = MutableList[1, 2, 3, 4, 5]

> l.sublist(..3)

> l

MutableList[1, 2, 3]

> def l = MutableList[1, 2, 3, 4, 5]

> l.sublist(..)

> l

MutableList[1, 2, 3, 4, 5]

method

method (mlst :: MutableList).contains(v :: Any,

                                      eqls :: Function.of_arity(2) = (_ == _))

  :: Boolean

Returns #true if mlst has an element equal to v, #false otherwise, where eqls determines equality. Searching the list takes O(N) time (multiplied by the cost of eqls) to find an element at position N. See also in.

> def l = MutableList[1, 2, 3]

> l.contains(2)

#true

> l.contains(200)

#false

> l.contains(-2, (fun (a, b): math.abs(a) == math.abs(b)))

#true

> 2 in l

#true

method

method (lst :: MutableList).index(v :: Any,

                                  eqls :: Function.of_arity(2) = (_ == _))

  :: maybe(Int)

Like MutableList.contains, but instead of returning #true, returns the index of a found element.

> def l = MutableList["a", "b", "c"]

> l.index("b")

1

> l.index("d")

#false

> l.index("B", fun (a, b): Char.downcase(a[0]) == Char.downcase(b[0]))

1

method

method (lst :: MutableList).find(pred :: Function.of_arity(1))

  :: Any

 

method

method (lst :: MutableList).find_index(pred :: Function.of_arity(1))

  :: maybe(NonnegInt)

Like List.find and List.index, but for mutable lists. Searching the list takes O(N) time (multiplied by the cost of pred) to find an element at position N.

> def l = MutableList[1, 2, 3]

> l.find((_ mod 2 .= 0))

2

> l.find((_ mod 10 .= 9))

#false

> l.find_index((_ mod 2 .= 0))

1

> l.find_index((_ mod 10 .= 9))

#false

method

method (mlst :: MutableList).remove(v :: Any) :: Void

Modifies mlst to remove the first element equal to v (if any). Searching the list takes O(N) time.

> def l = MutableList[1, 2, 3, 2]

> l.remove(2)

method

method (mlst :: MutableList).map(f :: Function.of_arity(1))

  :: Void

 

method

method (mlst :: MutableList).for_each(f :: Function.of_arity(1))

  :: Void

Similar to List.map and List.for_each, but MutableList.map modifies the mutable list to contain resulting items instead of returning a new list.

> def l = MutableList[1, 2, 3]

> MutableList.map(l, (_ + 1))

> l

MutableList[2, 3, 4]

> l.for_each(println)

2

3

4

method

method (mlst :: MutableList).filter(

  ~keep: keep_pred :: Function.of_arity(1),

  ~skip: skip_pred :: Function.of_arity(1)

) :: Void

Like List.filter, but modifies mlst by dropping each element for which keep_pred returns #false or skip_pred returns a true value.

> def l = MutableList[1, -1, -2, 2]

> l.filter(~keep: (_ > 0))

> l

MutableList[1, 2]

> def l = MutableList[1, -1, -2, 2]

> l.filter(~skip: (_ > 0))

> l

MutableList[-1, -2]

> def l = MutableList[1, -1, -2, 2]

> l.filter(~keep: (_ != -2), ~skip: (_ > 0))

> l

MutableList[-1]

method

method (mlst :: MutableList).sort(is_less :: Function.of_arity(2) = (_ < _))

  :: Void

Modifies mlst to contain its elements sorted using is_less to compare elements, Sorting takes O(N log N) time.

> def l = MutableList[1, 3, 2]

> MutableList.sort(l)

> l

MutableList[1, 2, 3]

> MutableList.sort(l, (_ > _))

> l

MutableList[3, 2, 1]

Equivalent to MutableList[& mlst], creates a new mutable list with the same elements as mlst.

> MutableList[1, 2, 3].copy()

MutableList[1, 2, 3]

method

method (mlst :: MutableList).to_list() :: List

 

method

method (mlst :: MutableList).snapshot() :: List

Implements Listable by returning a list containing the elements of mlst.

Implements Sequenceable by returning a sequence of mlst’s elements in order.