Packages
gleam_stdlib
0.7.0
1.0.3
1.0.2
1.0.1
1.0.0
0.71.0
0.70.0
0.69.0
0.68.1
0.68.0
0.67.1
0.67.0
0.65.0
0.64.0
0.63.2
0.63.1
0.63.0
0.62.1
0.62.0
0.61.0
0.60.0
0.59.0
0.58.0
0.57.0
0.56.0
0.55.0
0.54.0
0.53.0
0.52.0
0.51.0
0.50.0
0.49.0
0.48.0
0.47.0
0.46.0
0.45.0
0.44.0
0.43.0
0.42.0
0.41.0
0.40.0
0.39.0
0.38.0
0.37.0
0.36.0
0.35.1
0.35.0
0.34.0
0.33.1
0.33.0
0.32.1
0.32.0
0.31.0
0.30.2
0.30.1
0.30.0
0.29.2
0.29.1
0.29.0
0.28.2
0.28.1
0.28.0
0.27.0
0.26.1
0.26.0
0.25.0
0.24.0
0.23.0
0.22.3
0.22.2
0.22.1
0.22.0
0.21.0
0.20.0
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.18.0-rc1
0.17.1
0.17.0
0.16.0
0.15.0
0.14.0
0.13.0
0.12.0
0.11.0
0.10.1
0.10.0
0.9.0
0.8.0
0.7.0
0.6.0
0.5.0
0.4.0
0.4.0-rc1
0.3.1
0.3.0
0.2.0
retired
A standard library for the Gleam programming language
Current section
Files
Jump to
Current section
Files
src/gleam/list.gleam
import gleam/int
import gleam/pair
import gleam/order.{Order}
import gleam/result.{Option}
pub type LengthMismatch {
LengthMismatch
}
// Using the Erlang C BIF implementation.
//
pub external fn length(List(a)) -> Int = "erlang" "length"
// Using the Erlang C BIF implementation.
//
pub external fn reverse(List(a)) -> List(a) = "lists" "reverse"
pub fn is_empty(list: List(a)) -> Bool {
list == []
}
pub fn contains(list: List(a), has elem: a) -> Bool {
case list {
[] -> False
[head | rest] -> head == elem || contains(rest, elem)
}
}
pub fn head(list: List(a)) -> Option(a) {
case list {
[] -> result.none()
[x | _] -> Ok(x)
}
}
pub fn tail(list: List(a)) -> Option(List(a)) {
case list {
[] -> result.none()
[_ | xs] -> Ok(xs)
}
}
fn do_filter(list: List(a), fun: fn(a) -> Bool, acc: List(a)) -> List(a) {
case list {
[] -> reverse(acc)
[x | xs] -> {
let new_acc = case fun(x) {
True -> [x | acc]
False -> acc
}
do_filter(xs, fun, new_acc)
}
}
}
pub fn filter(list: List(a), for predicate: fn(a) -> Bool) -> List(a) {
do_filter(list, predicate, [])
}
fn do_map(list: List(a), fun: fn(a) -> b, acc: List(b)) -> List(b) {
case list {
[] -> reverse(acc)
[x | xs] -> do_map(xs, fun, [fun(x) | acc])
}
}
pub fn map(list: List(a), with fun: fn(a) -> b) -> List(b) {
do_map(list, fun, [])
}
fn do_index_map(
list: List(a),
fun: fn(Int, a) -> b,
index: Int,
acc: List(b),
) -> List(b) {
case list {
[] -> reverse(acc)
[x | xs] -> do_index_map(xs, fun, index + 1, [fun(index, x) | acc])
}
}
pub fn index_map(list: List(a), with fun: fn(Int, a) -> b) -> List(b) {
do_index_map(list, fun, 0, [])
}
fn do_traverse(
list: List(a),
fun: fn(a) -> Result(b, e),
acc: List(b),
) -> Result(List(b), e) {
case list {
[] -> Ok(reverse(acc))
[x | xs] ->
case fun(x) {
Ok(y) -> do_traverse(xs, fun, [y | acc])
Error(error) -> Error(error)
}
}
}
pub fn traverse(
list: List(a),
with fun: fn(a) -> Result(b, e),
) -> Result(List(b), e) {
do_traverse(list, fun, [])
}
pub fn drop(from list: List(a), up_to n: Int) -> List(a) {
case n <= 0 {
True -> list
False ->
case list {
[] -> []
[_ | xs] -> drop(xs, n - 1)
}
}
}
fn do_take(list: List(a), n: Int, acc: List(a)) -> List(a) {
case n <= 0 {
True -> reverse(acc)
False ->
case list {
[] -> reverse(acc)
[x | xs] -> do_take(xs, n - 1, [x | acc])
}
}
}
pub fn take(from list: List(a), up_to n: Int) -> List(a) {
do_take(list, n, [])
}
pub fn new() -> List(a) {
[]
}
pub external fn append(List(a), List(a)) -> List(a)
= "lists" "append";
fn do_flatten(lists: List(List(a)), acc: List(a)) -> List(a) {
case lists {
[] -> acc
[l | rest] -> do_flatten(rest, append(acc, l))
}
}
pub fn flatten(lists: List(List(a))) -> List(a) {
do_flatten(lists, [])
}
pub fn fold(list: List(a), from initial: b, with fun: fn(a, b) -> b) -> b {
case list {
[] -> initial
[x | rest] -> fold(rest, fun(x, initial), fun)
}
}
pub fn fold_right(
list: List(a),
from initial: b,
with fun: fn(a, b) -> b,
) -> b {
case list {
[] -> initial
[x | rest] -> fun(x, fold_right(rest, initial, fun))
}
}
pub fn find(
in haystack: List(a),
one_that is_desired: fn(a) -> Bool,
) -> Option(a) {
case haystack {
[] -> result.none()
[x | rest] ->
case is_desired(x) {
True -> Ok(x)
_ -> find(in: rest, one_that: is_desired)
}
}
}
pub fn find_map(
in haystack: List(a),
with fun: fn(a) -> Option(b),
) -> Option(b) {
case haystack {
[] -> result.none()
[x | rest] ->
case fun(x) {
Ok(x) -> Ok(x)
_ -> find_map(in: rest, with: fun)
}
}
}
pub fn all(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
case list {
[] -> True
[x | rest] ->
case predicate(x) {
True -> all(rest, predicate)
_ -> False
}
}
}
pub fn any(in list: List(a), satisfying predicate: fn(a) -> Bool) -> Bool {
case list {
[] -> False
[x | rest] ->
case predicate(x) {
False -> any(rest, predicate)
_ -> True
}
}
}
pub fn zip(xs: List(a), ys: List(b)) -> List(tuple(a, b)) {
case xs, ys {
[], _ -> []
_, [] -> []
[x | xs], [y | ys] -> [tuple(x, y) | zip(xs, ys)]
}
}
pub fn strict_zip(l1: List(a), l2: List(b)) -> Result(List(tuple(a, b)), LengthMismatch) {
case length(l1) == length(l2) {
True -> Ok(zip(l1, l2))
False -> Error(LengthMismatch)
}
}
pub fn intersperse(list: List(a), with elem: a) -> List(a) {
case list {
[] | [_] -> list
[x | rest] -> [x | [elem | intersperse(rest, elem)]]
}
}
pub fn at(in list: List(a), get index: Int) -> Option(a) {
case index < 0 {
True -> result.none()
False ->
case list {
[] -> result.none()
[x | rest] ->
case index == 0 {
True -> Ok(x)
False -> at(rest, index - 1)
}
}
}
}
pub fn unique(list: List(a)) -> List(a) {
case list {
[] -> []
[x | rest] -> [x | unique(filter(rest, fn(y) { y != x }))]
}
}
fn merge_sort(a: List(a), b: List(a), compare: fn(a, a) -> Order) -> List(a) {
case a, b {
[], _ -> b
_, [] -> a
[ax | ar], [bx | br] ->
case compare(ax, bx) {
order.Lt -> [ax | merge_sort(ar, b, compare)]
_ -> [bx | merge_sort(a, br, compare)]
}
}
}
fn do_sort(list: List(a), compare: fn(a, a) -> Order, list_length: Int) -> List(a) {
case list_length < 2 {
True -> list
False -> {
let split_length = list_length / 2
let a_list = take(list, split_length)
let b_list = drop(list, split_length)
merge_sort(
do_sort(a_list, compare, split_length),
do_sort(b_list, compare, list_length - split_length),
compare,
)
}
}
}
pub fn sort(list: List(a), sort_by compare: fn(a, a) -> Order) -> List(a) {
do_sort(list, compare, length(list))
}
pub fn range(from start: Int, to stop: Int) -> List(Int) {
case int.compare(start, stop) {
order.Eq -> []
order.Gt -> [start | range(start - 1, stop)]
order.Lt -> [start | range(start + 1, stop)]
}
}
fn do_repeat(a: a, times: Int, acc: List(a)) -> List(a) {
case times <= 0 {
True -> acc
False -> do_repeat(a, times - 1, [a | acc])
}
}
pub fn repeat(item a: a, times times: Int) -> List(a) {
do_repeat(a, times, [])
}
fn do_split(list: List(a), n: Int, taken: List(a)) -> tuple(List(a), List(a)) {
case n <= 0 {
True -> tuple(reverse(taken), list)
False ->
case list {
[] -> tuple(reverse(taken), [])
[x | xs] -> do_split(xs, n - 1, [x | taken])
}
}
}
pub fn split(list list: List(a), at index: Int) -> tuple(List(a), List(a)) {
do_split(list, index, [])
}
fn do_split_while(
list: List(a),
f: fn(a) -> Bool,
acc: List(a),
) -> tuple(List(a), List(a)) {
case list {
[] -> tuple(reverse(acc), [])
[x | xs] ->
case f(x) {
False -> tuple(reverse(acc), list)
_ -> do_split_while(xs, f, [x | acc])
}
}
}
pub fn split_while(
list list: List(a),
while predicate: fn(a) -> Bool,
) -> tuple(List(a), List(a)) {
do_split_while(list, predicate, [])
}
pub fn key_find(
in keyword_list: List(tuple(k, v)),
find desired_key: k,
) -> Option(v) {
find_map(keyword_list, fn(keyword) {
let tuple(key, value) = keyword
case key == desired_key {
True -> Ok(value)
False -> result.none()
}
})
}