On this page:
List
List.of
List
#%brackets
#%brackets
List
List
#%brackets
Nonempty  List
Nonempty  List.of
List
List.insert
List.add
List.cons
List.cons
List.empty
List.empty
List.get
List.first
List.last
List.rest
List.delete
List.set
List.length
List.reverse
List.append
List.take
List.take_  last
List.drop
List.drop_  last
List.sublist
List.has_  element
List.find
List.index
List.remove
List.map
List.for_  each
List.filter
List.partition
List.sort
List.iota
List.copy
List.to_  list
List.to_  sequence
List.repet
8.15.0.12

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—in O(log N) time—via #%index. A list also works with the ++ operator to append lists. A list can be used as sequence, in which case it supplies its elements in order.

annotation

List

 

annotation

List.of(annot)

Matches any list in the form without of. The of variant matches a list whose elements satisfy annot.

Static information associated by List or List.of makes an expression acceptable as a sequence to for in static mode.

function

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

 

expression

#%brackets [expr_or_splice, ...]

 

repetition

#%brackets [repet_or_splice, ...]

 

expression

List[expr_or_splice, ...]

 

repetition

List[repet_or_splice, ...]

 

expr_or_splice

 = 

expr

 | 

repet , ellipses

 | 

& listable_expr

 

ellipses

 = 

ellipsis

 | 

ellipses , ellipsis

 

ellipsis

 = 

...

Constructs a 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). List constructions can also serve as repetitions, where repet_or_splice is like expr_or_splice, but with repetitions in place of expressions.

The #%brackets form is implicitly used when [] is used in an expression position. See also Implicit Forms.

> def lst = List(1, 2, 3)

> lst

[1, 2, 3]

> lst[0]

1

> lst ++ [4, 5]

[1, 2, 3, 4, 5]

> #%brackets [1, 2, 3]

[1, 2, 3]

binding operator

List(bind_or_splice, ...)

 

binding operator

#%brackets [bind_or_splice, ...]

 

binding operator

List[bind_or_splice, ...]

 

bind_or_splice

 = 

bind

 | 

splice

 

splice

 = 

repet_bind , ellipsis

 | 

& list_bind

 | 

& list_repet_bind , ellipsis

 

ellipsis

 = 

...

 | 

... ~nonempty

 | 

... ~once

Matches a list with as many elements as binds, or if a splice is included, at least as many elements as binds. Each bind matches an element of the list. Each splice matches a sublist: repet_bind , ellipsis matches a sublist of elements that individually match repet_bind, & list_bind matches a sublist that itself matches list_bind, and & list_repet_bind , ellipsis matches a sublist that is a concatenation of sublists that each match list_repet_bind. If ellipsis includes ~nonempty, then the matching sublist must have at least one element, otherwise the matching sublist can be empty. If ellipsis includes ~once, then a matching sublist has 0 or 1 elements. A matching sublist is deterministic if only one splice is present with & or ... (but not both).

> def List(1, x, y) = [1, 2, 3]

> y

3

> def [1, also_x, also_y] = [1, 2, 3]

> also_y

3

> def List(1, & xs) = [1, 2, 3]

> xs

[2, 3]

> def List(1, x, ...) = [1, 2, 3]

> [x, ...]

[2, 3]

> def List(1, x, ..., 3) = [1, 2, 3]

> [x, ...]

[2]

> def List(1, x, ... ~nonempty, 3) = [1, 2, 3]

> [x, ...]

[2]

> def List(1, x, ... ~nonempty, 3) = [1, 3]

def: value does not satisfy annotation

  value: [1, 3]

  annotation: matching(List(1, _, ... ~nonempty, 3))

> def List(1, x, ... ~once, 3) = [1, 3]

> def List(1, x, ... ~once, 3) = [1, 2, 2, 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.

> def List(x, ..., z, ...) = [1, 2, "c", 5]

> [[x, ...], [z, ...]]

[[1, 2, "c", 5], []]

> def List(x, ..., z, ... ~nonempty) = [1, 2, "c", 5]

> [[x, ...], [z, ...]]

[[1, 2, "c"], [5]]

> def List(x, ..., #'stop, z, ...) = [1, 2, "c", #'stop, 5]

> [[x, ...], [z, ...]]

[[1, 2, "c"], [5]]

> def List(x :: Int, ..., y, z, ...) = [1, 2, "c", "d", 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.

> def List(& [x, ...], ...) = [1, 2, 3, 4]

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

NonemptyList

 

annotation

NonemptyList.of(annot)

Like List as an annotation, but matches only non-empty lists.

> [1] :: NonemptyList

[1]

> [] :: NonemptyList

::: value does not satisfy annotation

  value: []

  annotation: NonemptyList

reducer

List

A reducer used with for, accumulates each result of a for body into a result list.

method

method (lst :: List).insert(n :: NonnegInt, elem :: Any) :: List

Creates a list like lst, but with elem added 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.

> List.insert(["a", "b", "c"], 1, "x")

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

method

method (lst :: List).add(elem :: Any) :: List

Creates a list like lst, but with elem added to the end, equivalent to lst.insert(lst.length(), elem).

> List.add([2, 3], 1)

[2, 3, 1]

> [2, 3].add(1)

[2, 3, 1]

> block:

    let l = [2, 3]

    l.insert(l.length(), 1)

[2, 3, 1]

function

fun List.cons(elem :: Any, lst :: List) :: List

Creates a list like lst, but with elem added to the front, equivalent to lst.insert(0, elem).

> List.cons(1, [2, 3])

[1, 2, 3]

> [2, 3].insert(0, 1)

[1, 2, 3]

binding operator

List.cons(elem_bind, list_bind)

Matches a non-empty list where elem_bind matches the first element of the list and list_bind matches the rest of the list. Static information associated by List is propagated to list_bind.

> def List.cons(x, y) = [1, 2, 3]

> x

1

> y

[2, 3]

value

def List.empty :: List = []

 

binding operator

List.empty

A name and pattern for the empty list.

method

method (lst :: List).get(n :: NonnegInt) :: Any

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

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

"b"

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

"b"

property

property List.first(lst :: NonemptyList) :: Any

Returns the first element of lst. Accessing the first element takes O(log N) time.

> List.first(["a", "b", "c"])

"a"

> ["a", "b", "c"].first

"a"

property

property List.last(lst :: NonemptyList) :: Any

Returns the last element of lst. Accessing the last element takes O(log N) time.

> List.last(["a", "b", "c"])

"c"

> ["a", "b", "c"].last

"c"

property

property List.rest(lst :: NonemptyList) :: List

Returns a list like lst, but without its first element. Creating the list takes O(log N) time.

> List.rest(["a", "b", "c"])

["b", "c"]

> ["a", "b", "c"].rest

["b", "c"]

method

method (lst :: List).delete(n :: NonnegInt) :: List

Creates a list like lst, but without the nth element. The n index must be less than the length of lst. Deletion takes O(log N) time.

> List.delete(["a", "b", "c"], 1)

["a", "c"]

method

method (lst :: List).set(n :: NonnegInt, v :: Any) :: List

Returns a list like lst, but with the nth element replaced with v, equivalent to lst.delete(n).insert(n, v). Note that this function performs a functional update, as opposed to mutable, which means lists do not implement MutableIndexable.

> ["a", "b", "c"].set(1, "beta")

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

> ["a", "b", "c"].delete(1).insert(1, "beta")

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

method

method (lst :: List).length() :: NonnegInt

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

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

3

> [].length()

0

method

method (lst :: List).reverse() :: List

Returns a list with the same items as lst, but in reversed order. Reversing a list takes O(N log N) time, equivalent asymptotically to adding each element of lst to another list one at a time.

> [1, 4, 8].reverse()

[8, 4, 1]

method

method (lst :: List).append(lst :: List, ...) :: List

 

function

fun List.append(lst :: List, ...) :: List

Appends the lsts in order. See also ++. Appending takes O(log N) time, which is asymptotically faster than adding each element one at a time from one list to the other.

> [1, 2, 3].append([4, 5], [6])

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

> List.append([1, 2, 3], [4, 5], [6])

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

> List.append()

[]

method

method (lst :: List).take(n :: NonnegInt) :: List

 

method

method (lst :: List).take_last(n :: NonnegInt) :: List

Returns a list like lst, but with only the first n elements in the case of List.take, or only the last n elements in the case of List.take_last. The given lst must have at least n elements, otherwise an Exn.Fail.Contract exception is thrown. Creating the new list takes O(log N) time, which is asymptotically faster than building a new list by adding or removing elements one at a time.

> [1, 2, 3, 4, 5].take(2)

[1, 2]

> [1, 2, 3, 4, 5].take_last(2)

[4, 5]

> [1].take(2)

List.take: index is out of range

  index: 2

  valid range: [0, 1]

  list: [1]

method

method (lst :: List).drop(n :: NonnegInt) :: List

 

method

method (lst :: List).drop_last(n :: NonnegInt) :: List

Returns a list like lst, but without the first n elements in the case of List.drop, or without the last n elements in the case of List.drop_last. The given lst must have at least n elements, otherwise an Exn.Fail.Contract exception is thrown. Creating the new list takes O(log N) time, which is asymptotically faster than building a new list by adding or removing elements one at a time.

> [1, 2, 3, 4, 5].drop(2)

[3, 4, 5]

> [1, 2, 3, 4, 5].drop_last(2)

[1, 2, 3]

> [1].drop(2)

List.drop: index is out of range

  index: 2

  valid range: [0, 1]

  list: [1]

method

method (lst :: List).sublist(n :: NonnegInt, m :: NonnegInt) :: List

Returns a sublist of lst containing elements from index n (inclusive) to m (exclusive), equivalent to lst.drop(n).take(m-n).

> [1, 2, 3, 4, 5].sublist(1, 3)

[2, 3]

> [1, 2, 3, 4, 5].drop(1).take(3-1)

[2, 3]

method

method (lst :: List).has_element(v :: Any,

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

  :: Boolean

Returns #true if lst 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 as position N.

> [1, 2, 3].has_element(2)

#true

> [1, 2, 3].has_element(200)

#false

method

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

  :: Any

 

method

method (lst :: List).index(pred :: Function.of_arity(1))

  :: maybe(NonnegInt)

The List.find function finds the first element of lst for which pred returns a true value, or it returns #false if no such element is found. The List.find function is similar, but it returns the index of the found element instead of the element. Searching the list takes O(N) time (multiplied by the cost of pred) to find an element as position N.

> [1, 2, 3].find((_ mod 2 .= 0))

2

> [1, 2, 3].find((_ mod 10 .= 9))

#false

> [1, 2, 3].index((_ mod 2 .= 0))

1

> [1, 2, 3].index((_ mod 10 .= 9))

#false

method

method (lst :: List).remove(v :: Any) :: List

Returns a list like lst, but with the first element equal to v (if any) removed. Searching the list takes O(N) time.

> [1, 2, 3, 2].remove(2)

[1, 3, 2]

method

method (lst :: List).map(f :: Function.of_arity(1))

  :: List

 

method

method (lst :: List).for_each(f :: Function.of_arity(1))

  :: Void

Like Function.map and Function.for_each, but with a single list of arguments first, with the function supplied second.

> List.map([1, 2, 3], (_ + 1))

[2, 3, 4]

> [1, 2, 3].map((_ + 1))

[2, 3, 4]

> [1, 2, 3].for_each(println)

1

2

3

method

method (lst :: List).filter(

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

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

) :: List

 

method

method (lst :: List).partition(pred :: Function.of_arity(1))

  :: values(List, List)

The List.filter function returns a list that is like lst, but drops any element for which keep_pred returns #false or skip_pred returns a true value. If keep_pred returns #false for a value, then skip_pred is not called for that value.

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, -1, -2, 2].filter(~keep: (_ > 0))

[1, 2]

> [1, -1, -2, 2].filter(~skip: (_ > 0))

[-1, -2]

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

[-1]

> [1, -1, -2, 2].partition((_ > 0))

[1, 2]

[-1, -2]

method

method (lst :: List).sort(is_less :: Function.of_arity(2) = (_ < _))

  :: List

Sorts lst using is_less to compare elements. Sorting takes O(N log N) time.

> List.sort([1, 3, 2])

[1, 2, 3]

> List.sort([1, 3, 2], (_ > _))

[3, 2, 1]

Returns a list containing the integers 0 to n (exclusive) in order.

> List.iota(3)

[0, 1, 2]

> List.iota(0)

[]

method

method (lst :: List).copy() :: MutableList

Equivalent to MutableList(& lst), creates a new mutable list with the same elements as lst.

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

MutableList[1, 2, 3]

method

method (lst :: List).to_list() :: List

Implements Listable by returning lst unchanged.

method

method (lst :: List).to_sequence() :: Sequence

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

Creates a repetition from a list. This is a shorthand for using ... with a List binding.

> def lst = [1, 2, 3]

> block:

    let [x, ...] = lst

    [x+1, ...]

[2, 3, 4]

> [List.repet(lst) + 1, ...]

[2, 3, 4]