List

List Builtin.List(_item) :: # (opaque)
parser_for : _
len : List(_item) -> U64

Returns the length of the list, which is equal to the number of items it contains.

One List can store up to I64.highest items on 64-bit targets and I32.highest on 32-bit targets like wasm. This means the #U64 this function returns can always be safely converted to #I64 or #I32, depending on the target.

is_empty : List(_item) -> Bool

Check if the list is empty.

[1, 2, 3].is_empty()

[].is_empty()
iter : List(item) -> Iter(item)

Iterate over the list from first to last.

from_iter : Iter(item) -> List(item)

Build a list from a pure Iter, pre-sizing the allocation from the iterator's len_if_known when it is known up front. This is the from_iter that Iter.collect dispatches to.

concat : List(item), List(item) -> List(item)

Put two lists together.

[1.I64, 2, 3].concat([4, 5])

[0.I64, 1, 2].concat([3, 4])
join : List(List(item)) -> List(item)

Concatenate a list of lists into a single list, preserving order.

You may know a similar function named flatten in other languages, although flatten sometimes flattens multiple levels of nesting; this only "flattens" one level.

expect [[1.I64, 2], [3], [], [4, 5]].join() == [1, 2, 3, 4, 5]

expect List.join([["a", "b"], ["c"]]) == ["a", "b", "c"]
join_map : List(a), (a -> List(b)) -> List(b)

Map each item to a list and concatenate the results, preserving order.

You may know a similar function named flat_map or concat_map in other languages.

expect [1.I64, 2, 3].join_map(|n| [n, n * 10]) == [1, 10, 2, 20, 3, 30]

expect ["a", "b"].join_map(|s| [s, s]) == ["a", "a", "b", "b"]
intersperse : List(a), a -> List(a)

Insert a separator between every pair of items in a list.

expect [1.I64, 2, 3].intersperse(0) == [1, 0, 2, 0, 3]

expect [1.I64].intersperse(0) == [1]
with_capacity : U64 -> List(item)

Create a list with space for at least capacity items

reserve : List(item), U64 -> List(item)

Ensure this list has room for at least spare additional items.

release_excess_capacity : List(item) -> List(item)

Reduce memory usage by trimming unused capacity.

sort_with : List(item), (item, item -> [LT, EQ, GT]) -> List(item)

Sort a list using a custom comparison function. The comparator receives two items and returns LT, EQ, or GT to indicate their relative order.

expect [3, 1, 2].sort_with(|a, b| if a < b LT else if a > b GT else EQ) == [1, 2, 3]

# Sort in descending order by swapping the LT and GT
expect [3, 1, 2].sort_with(|a, b| if a > b LT else if a < b GT else EQ) == [3, 2, 1]
is_eq : List(item), List(item) -> Bool where [item.is_eq : item, item -> Bool]

Returns True if the two lists have the same length and their items are pairwise equal.

to_hash : List(item), Hasher -> Hasher where [item.to_hash : item, Hasher -> Hasher]

Feed a list into a Hasher.

append : List(a), a -> List(a)

Add a single item to the end of a list.

[1.I64, 2, 3].append(4)

[0.I64, 1, 2].append(3)
append_if_ok : List(a), Try(a, err) -> List(a)

Add the Ok payload to the end of a list, or leave the list unchanged if the value is Err.

expect List.append_if_ok([1, 2], Ok(3)) == [1, 2, 3]

expect List.append_if_ok([1, 2], Err(NotFound)) == [1, 2]
prepend_if_ok : List(a), Try(a, err) -> List(a)

Add the Ok payload to the beginning of a list, or leave the list unchanged if the value is Err.

expect List.prepend_if_ok([2, 3], Ok(1)) == [1, 2, 3]

expect List.prepend_if_ok([2, 3], Err(NotFound)) == [2, 3]
prepend : List(a), a -> List(a)

Add a single item to the beginning of a list.

expect [2, 3, 4].prepend(1) == [1, 2, 3, 4]

expect [].prepend(0) == [0]
first : List(item) -> Try(item, [ListWasEmpty, ..])

Returns the first item in the list, or ListWasEmpty if it was empty.

expect [1, 2, 3].first() == Ok(1)
expect [].first() == Err(ListWasEmpty)
get : List(item), U64 -> Try(item, [OutOfBounds, ..])

Returns an item from a list at the given index.

Returns Err OutOfBounds if the given index exceeds the List's length

expect [100, 200, 300].get(1) == Ok(200)
expect [100, 200, 300].get(5) == Err(OutOfBounds)
subscript : List(item), U64 -> Try(item, [OutOfBounds, ..])

Alias for List.get, enabling the future list[index] subscript operator. Returns an item from a list at the given index.

Returns Err OutOfBounds if the given index exceeds the List's length

expect ["bird", "lizard"].subscript(0) == Ok("bird")
expect ["bird", "lizard"].subscript(5) == Err(OutOfBounds)
get_wrap : List(item), U64 -> Try(item, [ListWasEmpty, ..])

Returns the item at the given index, wrapping back to the start when the index is past the end (the index is taken modulo the length).

You may know a similar function named getWrap, or indexing that wraps a negative or out-of-range index, in other languages.

Returns Err(ListWasEmpty) if the list is empty.

expect ["a", "b", "c"].get_wrap(4) == Ok("b")
set : List(a), U64, a -> Try(List(a), [OutOfBounds, ..])

Replaces the item at the given index with a new value.

expect [10, 20, 30].set(1, 99) == Ok([10, 99, 30])

expect [10, 20, 30].set(5, 99) == Err(OutOfBounds)
replace : List(a), U64, a -> Try({ list : List(a), prev : a }, [OutOfBounds, ..])

Replaces the item at the given index, returning both the updated list and the value that was replaced.

expect [10, 20, 30].replace(1, 99) == Ok({ list: [10, 99, 30], prev: 20 })
expect [10, 20, 30].replace(5, 99) == Err(OutOfBounds)
update : List(a), U64, (a -> a) -> Try(List(a), [OutOfBounds, ..])

Updates the item at the given index by applying a function to it.

expect [10, 20, 30].update(1, |x| x + 5) == Ok([10, 25, 30])

expect [10, 20, 30].update(5, |x| x + 5) == Err(OutOfBounds)
swap : List(a), U64, U64 -> Try(List(a), [OutOfBounds, ..])

Exchanges the items at the two given indices.

expect [10, 20, 30, 40].swap(0, 3) == Ok([40, 20, 30, 10])

expect [10, 20, 30].swap(0, 5) == Err(OutOfBounds)
insert : List(a), U64, a -> Try(List(a), [OutOfBounds, ..])

Inserts an item at the given index, shifting later items toward the end. An index equal to the length appends the item; a greater index is out of bounds.

expect [1.I64, 2, 3].insert(1, 9) == Ok([1, 9, 2, 3])

expect [1.I64, 2, 3].insert(5, 9) == Err(OutOfBounds)
rev : List(item) -> List(item)

Returns the reversed list.

expect [1, 2, 3].rev() == [3, 2, 1]
expect [].rev() == []
for_each! : List(item), (item => {  }) => {  }
map : List(a), (a -> b) -> List(b)

Convert each item in the list to something new, by calling a conversion function on each of them. Then return a new list of the converted values.

expect [1, 2, 3].map(|num| num + 1) == [2, 3, 4]

expect ["", "a", "bc"].map(Str.is_empty) == [Bool.True, Bool.False, Bool.False]
map_with_index : List(a), (a, U64 -> b) -> List(b)

This works like List.map, except it also passes the index of the item to the conversion function.

expect List.map_with_index([10, 20, 30], (|num, index| num + index)) == [10, 21, 32]
map2 : List(a), List(b), (a, b -> c) -> List(c)

Apply a binary function to pairs of items from two lists, returning a list of results. The result's length is the length of the shorter input list.

expect [1, 2, 3].map2([10, 20, 30], |a, b| a + b) == [11, 22, 33]
expect [1, 2, 3, 4, 5].map2([10, 20], |a, b| a + b) == [11, 22]
map3 : List(a), List(b), List(c), (a, b, c -> d) -> List(d)

Apply a ternary function to triples of items from three lists, returning a list of results. The result's length is the length of the shortest input list.

expect [1, 2, 3].map3([10, 20, 30], [100, 200, 300], |a, b, c| a + b + c) == [111, 222, 333]
expect [1, 2, 3, 4, 5].map3([10, 20], [100, 200, 300], |a, b, c| a + b + c) == [111, 222]
map4 : List(a), List(b), List(c), List(d), (a, b, c, d -> e) -> List(e)

Apply a quaternary function to groups of items from four lists, returning a list of results. The result's length is the length of the shortest input list.

expect [1, 2, 3].map4([10, 20, 30], [100, 200, 300], [1000, 2000, 3000], |a, b, c, d| a + b + c + d) == [1111, 2222, 3333]
expect [1, 2, 3, 4, 5].map4([10, 20], [100, 200, 300], [1000, 2000, 3000, 4000], |a, b, c, d| a + b + c + d) == [1111, 2222]
keep_if : List(a), (a -> Bool) -> List(a)

Run the given function on each item of a list, and return all the items for which the function returned Bool.True.

[1.I64, 2, 3, 4].keep_if(|num| num > 2)

## Performance Details

List.keep_if always returns a list that takes up exactly the same amount of memory as the original, even if its length decreases. This is because it can't know in advance exactly how much space it will need, and if it guesses a length that's too low, it would have to re-allocate.

(If you want to do an operation like this which reduces the memory footprint of the resulting list, you can do two passes over the list with List.fold - one to calculate the precise new size, and another to populate the new list.)

If given a unique list, List.keep_if will mutate it in place to assemble the appropriate list. If that happens, this function will not allocate any new memory on the heap. If all items in the list end up being kept, Roc will return the original list unaltered.

drop_if : List(a), (a -> Bool) -> List(a)

Run the given function on each item of a list, and return all the items for which the function returned Bool.False.

[1.I64, 2, 3, 4].drop_if(|num| num > 2)

## Performance Details

List.drop_if has the same performance characteristics as List.keep_if. See its documentation for details on those characteristics!

keep_oks : List(before), (before -> Try(after, _err)) -> List(after)

Run the given function on each item of a list, and return a list of the values it wrapped in Ok. Items the function maps to Err are dropped. Use List.keep_errs to keep the Err values instead.

expect [1.I64, 2, 3, 4].keep_oks(|n| if n.is_even() { Ok(n) } else { Err({}) }) == [2, 4]
keep_errs : List(before), (before -> Try(_ok, after)) -> List(after)

Run the given function on each item of a list, and return a list of the values it wrapped in Err. Items the function maps to Ok are dropped. Use List.keep_oks to keep the Ok values instead.

expect [1.I64, 2, 3, 4].keep_errs(|n| if n.is_even() { Ok(n) } else { Err(n) }) == [1, 3]
count_if : List(a), (a -> Bool) -> U64

Run the given function on each item of a list, and return the number of items for which the function returned Bool.True.

expect [1, -2, -3].count_if(I64.is_negative) == 2
expect [1, 2, 3].count_if(|num| num > 1) == 2
map_try : List(a), (a -> Try(b, err)) -> Try(List(b), err)

Like List.map, but the transform can fail. Runs a Try-returning function on each item and collects the Ok values. Stops at the first Err and returns it, so the result is either all the transformed values or the first failure.

expect [1.I64, 2, 3].map_try(|n| if n < 3 { Ok(n) } else { Err(TooBig) }) == Err(TooBig)
map_try! : List(a), (a => Try(b, err)) => Try(List(b), err)

Like List.map_try, but the transform is effectful. It runs on each item until one returns Err, then stops.

rows.map_try!(|row| SQL.insert!("INSERT INTO t VALUES (?)", [row]))
keep_if_try : List(a), (a -> Try(Bool, err)) -> Try(List(a), err)

Like List.keep_if, but the predicate can fail. Runs a Try-returning predicate on each item, keeping the ones it maps to Ok(Bool.True). Stops at the first Err and returns it.

expect [1.I64, 2, 3].keep_if_try(|n| Ok(n > 1)) == Ok([2, 3])
keep_if_try! : List(a), (a => Try(Bool, err)) => Try(List(a), err)

Like List.keep_if_try, but the predicate is effectful. It runs on each item until one returns Err, then stops.

users.keep_if_try!(|user| SQL.query_bool!("SELECT is_active FROM users WHERE id = ?", [user.id]))
fold_try : List(item), state, (state, item -> Try(state, err)) -> Try(state, err)

Like List.fold, but the step function can fail. Threads state through the list, and if a step returns Err, stops and returns it.

expect [1.I64, 2, 3].fold_try(0, |sum, n| if n < 3 { Ok(sum + n) } else { Err(Stop) }) == Err(Stop)
fold_try! : List(item), state, (state, item => Try(state, err)) => Try(state, err)

Like List.fold_try, but the step function is effectful. It runs on each item until one returns Err, then stops.

events.fold_try!(State.init, |state, event| Store.apply!(state, event))
fold : List(item), state, (state, item -> state) -> state

Build a value using each item in the list.

Starting with a given state value, this folds through each item in the list from first to last, running a given step function on that item which updates the state. It returns the final state at the end.

[2, 4, 8].fold(0, U64.plus)

This returns 14 because: * state starts at 0 * Each step runs state.plus(item), and the return value becomes the new state.

Here is a table of how state changes as List.fold folds over the items [2, 4, 8] using U64.plus as its step function to determine the next state.

state | item | U64.plus(state, item) :---: | :---: | :----------------: 0 | | 0 | 2 | 2 2 | 4 | 6 6 | 8 | 14

The following returns -6:

[1, 2, 3].fold(0, I64.minus)

Note that in other languages, fold is sometimes called reduce, fold_left, or foldl.

fold_with_index : List(item), state, (state, item, U64 -> state) -> state

Like List.fold, but at each step the function also receives the index of the current item.

fold_until : List(item), state, (state, item -> [Continue(state), Break(state)]) -> state

Same as List.fold, except you can stop folding early.

## Performance Details

Compared to List.fold, this can potentially visit fewer items (which can improve performance) at the cost of making each step take longer. However, the added cost to each step is extremely small, and can easily be outweighed if it results in skipping even a small number of items.

As such, it is typically better for performance to use this over List.fold if returning Break earlier than the last item is expected to be common.

fold_with_index_until : List(item), state, (state, item, U64 -> [Continue(state), Break(state)]) -> state

Same as List.fold_with_index, except you can stop folding early.

fold_rev : List(item), state, (item, state -> state) -> state

Like List.fold, but walks the list from last to first. The step function receives the item first and the current state second.

expect [1, 2, 3].fold_rev(0, I64.minus) == 2

Here is a table of how state changes as List.fold_rev folds over the items [1, 2, 3] using I64.minus as its step function.

state | item | I64.minus(item, state) :---: | :---: | :-------------------: 0 | | 0 | 3 | 3 3 | 2 | -1 -1 | 1 | 2

Note that in other languages, fold_rev is sometimes called reduce_right, fold_right, or foldr.

starts_with : List(a), List(a) -> Bool where [a.is_eq : a, a -> Bool]

Returns Bool.True if the first list starts with the second list.

If the second list is empty, this always returns Bool.True; every list is considered to "start with" an empty list.

If the first list is empty, this only returns Bool.True if the second list is empty.

ends_with : List(a), List(a) -> Bool where [a.is_eq : a, a -> Bool]

Returns Bool.True if the first list ends with the second list.

If the second list is empty, this always returns Bool.True; every list is considered to "end with" an empty list.

If the first list is empty, this only returns Bool.True if the second list is empty.

any : List(a), (a -> Bool) -> Bool

Run the given predicate on each item of the list, returning Bool.True if any of the items satisfy it.

expect [1, 2, 3].any(|n| n % 2 == 0)

expect ![1, 2, 3].any(|n| n < 0)
contains : List(a), a -> Bool where [a.is_eq : a, a -> Bool]

Returns Bool.True if the list contains an item equal to the given value.

expect [1, 2, 3].contains(2)

expect ![1, 2, 3].contains(4)
all : List(a), (a -> Bool) -> Bool

Run the given predicate on each item of the list, returning Bool.True if all of the items satisfy it.

expect [2, 4, 6].all(|n| n % 2 == 0)

expect ![1, 2, 3].all(|n| n % 2 == 0)
last : List(item) -> Try(item, [ListWasEmpty, ..])

Returns the last item in the list, or ListWasEmpty if it was empty.

expect [1, 2, 3].last() == Ok(3.0)
expect [].last() == Err(ListWasEmpty)
single : item -> List(item)

Create a list with a single item in it.

expect List.single(42) == [42.0]
drop_at : List(a), U64 -> List(a)

Remove the item at the given index. If the index is out of bounds, the list is returned unchanged.

expect [10, 20, 30, 40].drop_at(1) == [10, 30, 40]

expect [10, 20, 30].drop_at(5) == [10, 20, 30]
drop_swap : List(a), U64 -> List(a)

Removes the item at the given index by moving the last item into its place, so the order of the remaining items is not preserved. This is O(1), unlike drop_at, which shifts every later item down.

Returns the list unchanged if the index is out of bounds.

expect [1.I64, 2, 3, 4].drop_swap(1) == [1, 4, 3]
sublist : List(a), { start : U64, len : U64 } -> List(a)

Return a sublist of the list starting at start and containing up to len items. Out-of-bounds ranges are clamped, producing a shorter or empty list.

expect [1, 2, 3, 4, 5].sublist({ start: 1, len: 3 }) == [2, 3, 4]

expect [1, 2, 3].sublist({ start: 1, len: 10 }) == [2, 3]

expect [1, 2, 3].sublist({ start: 10, len: 2 }) == []
chunks_of : List(a), U64 -> List(List(a))

Split a list into chunks of at most chunk_size items, in order. The final chunk is shorter when the length is not a multiple of chunk_size, and a chunk_size of 0 produces an empty list.

expect [1.I64, 2, 3, 4, 5].chunks_of(2) == [[1, 2], [3, 4], [5]]

expect [1.I64, 2, 3].chunks_of(10) == [[1, 2, 3]]
take_first : List(a), U64 -> List(a)

Return the first n items of the list. If the list has fewer than n items, the entire list is returned.

expect [1, 2, 3, 4, 5].take_first(3) == [1, 2, 3]

expect [1, 2].take_first(10) == [1, 2]
clear : List(a) -> List(a)

Removes every item while preserving the current capacity.

expect [1.I64, 2, 3].clear() == []
take_last : List(a), U64 -> List(a)

Returns the given number of items from the end of the list.

expect [1, 2, 3, 4, 5, 6, 7, 8].take_last(4) == [5, 6, 7, 8]

If there are fewer items in the list than the requested number, the entire list is returned.

expect [1, 2].take_last(5) == [1, 2]

To *remove* items from the end of the list, use List.take_first.

To remove items from both the beginning and end of the list, use List.sublist.

drop_first : List(a), U64 -> List(a)

Drops n items from the beginning of the list. If n is larger than the list length, an empty list is returned.

expect [1, 2, 3, 4, 5].drop_first(2) == [3, 4, 5]

expect [1, 2, 3].drop_first(10) == []
drop_last : List(a), U64 -> List(a)

Drops n items from the end of the list. If n is larger than the list length, an empty list is returned.

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

expect [1, 2, 3].drop_last(10) == []
find_first : List(a), (a -> Bool) -> Try(a, [NotFound])

Find the first item in a list that satisfies a given predicate, returning it wrapped in Ok if found, or Err(NotFound) if no such item exists.

expect [1, 2, 3, 4].find_first(|x| x % 2 == 0) == Ok(2)
find_last : List(a), (a -> Bool) -> Try(a, [NotFound])

Find the last item in a list that satisfies a given predicate, returning it wrapped in Ok if found, or Err(NotFound) if no such item exists.

expect [1, 2, 3, 4].find_last(|x| x % 2 == 0) == Ok(4)
find_first_index : List(a), (a -> Bool) -> Try(U64, [NotFound])

Find the index of the first item in a list that satisfies a given predicate, returning it wrapped in Ok if found, or Err(NotFound) if no such item exists.

expect [1, 2, 3, 4].find_first_index(|x| x > 1) == Ok(1)
find_last_index : List(a), (a -> Bool) -> Try(U64, [NotFound])

Find the index of the last item in a list that satisfies a given predicate, returning it wrapped in Ok if found, or Err(NotFound) if no such item exists.

expect [1, 2, 3, 4].find_last_index(|x| x < 4) == Ok(2)
split_at : List(a), U64 -> { before : List(a), others : List(a) }
expect [0, 1, 2, 3, 4].split_at(2) == { before: [0, 1], others: [2, 3, 4] }
split_on : List(a), a -> List(List(a)) where [a.is_eq : a, a -> Bool]

Split a list into sublists using a specified delimiter item.

Consecutive delimiters and delimiters at the start or end of the list produce empty sublists at the corresponding positions.

expect [1, 2, 1, 2, 3].split_on(1) == [[], [2], [2, 3]]
expect [1, 1, 2].split_on(1) == [[], [], [2]]
split_if : List(a), (a -> Bool) -> List(List(a))

Split a list into sublists using a predicate function to identify delimiters.

Consecutive delimiters and delimiters at the start or end of the list produce empty sublists at the corresponding positions.

expect [0, 1, 2, 3, 4].split_if(|x| x % 2 == 0) == [[], [1], [3], []]
split_on_list : List(a), List(a) -> List(List(a)) where [a.is_eq : a, a -> Bool]

Split a list into sublists using a specified delimiter list.

expect [1, 2, 3, 4, 5].split_on_list([2, 3]) == [[1], [4, 5]]
split_first : List(a), a -> Try({ before : List(a), after : List(a) }, [NotFound]) where [a.is_eq : a, a -> Bool]

Split a list into two parts at the first occurrence of a specified delimiter item, returning the part before the delimiter and the part after it. If the delimiter is not found, return Err(NotFound).

expect [0, 1, 2, 1, 2].split_first(2) == Ok({ before: [0, 1], after: [1, 2] })
split_last : List(a), a -> Try({ before : List(a), after : List(a) }, [NotFound]) where [a.is_eq : a, a -> Bool]

Split a list into two parts at the last occurrence of a specified delimiter item, returning the part before the delimiter and the part after it. If the delimiter is not found, return Err(NotFound).

expect [0, 1, 2, 1, 2].split_last(1) == Ok({ before: [0, 1, 2], after: [2] })
repeat : a, U64 -> List(a)

Build a list by repeating the given value n times.

expect List.repeat(0, 3) == [0, 0, 0]

expect List.repeat("hi", 0) == []
sum : List(item) -> item where [item.plus : item, item -> item, item.default : () -> item]

Sum the items of a list. Works for any type that implements plus and default methods, such as the numeric types.

default is called only when the list is empty; otherwise it is never called at all. Summing begins at the first item and uses plus to combine the rest, so a single-item list returns that item without calling either method, and default does not need to be an identity value for plus.

expect List.sum([1.I64, 2, 3, 4]) == 10

expect List.sum([42.I64]) == 42

expect List.sum([]) == 0.I64
min : List(a) -> Try(a, [ListWasEmpty]) where [a.min : a, a -> a]

Find the minimum item in a list, or Err(ListWasEmpty) if the list is empty. Works for any type that implements min.

max : List(a) -> Try(a, [ListWasEmpty]) where [a.max : a, a -> a]

Find the maximum item in a list, or Err(ListWasEmpty) if the list is empty. Works for any type that implements max.

encoder_for : encoding -> List(item), state -> Try(state, err)
    where [
        item.encoder_for : encoding -> item, state -> Try(state, err),
        encoding.encode_list : state, U64, (container_state, (container_state, (state -> Try(state, err)) -> Try(container_state, err)) -> Try(container_state, err)) -> Try(state, err),
    ]

Build an encoder for a list using a format that provides a list encoding method.

decode : src, fmt -> (Try(List(item), err), src)
    where [
        fmt.decode_list : fmt, src, (src, fmt -> (Try(item, err), src)) -> (Try(List(item), err), src),
        item.decode : src, fmt -> (Try(item, err), src),
    ]

Decode a list using a format that provides decode_list