aiken/pairs

A module for working with associative lists (a.k.a Pairs).

While any function that works on List also work on Pairs, this module provides some extra helpers that are specifically tailored to working with associative lists. Fundamentally, a Pairs<k, v> is a type-alias to List<Pair<k, v>>.

Important

Unlike dictionnaries (a.k.a. Dict), associative lists make no assumption about the ordering of elements within the list. As a result, lookup functions do traverse the entire list when invoked. They are also not sets, and thus allow for duplicate keys. This is reflected in the functions used to interact with them.

Functions

find_all(self: Pairs<key, value>, v: value) -> List<key>

Finds all keys in the alist associated with a given value.

pairs.find_all([], 1) == []
pairs.find_all([Pair("a", 1)], 1) == ["a"]
pairs.find_all([Pair("a", 1), Pair("b", 2)], 1) == ["a"]
pairs.find_all([Pair("a", 1), Pair("b", 2), Pair("c", 1)], 1) == ["a", "c"]

find_first(self: Pairs<key, value>, v: value) -> Option<key>

Finds the first key in the alist associated with a given value, if any.

pairs.find_first([], 1) == None
pairs.find_first([Pair("a", 1)], 1) == Some("a")
pairs.find_first([Pair("a", 1), Pair("b", 2)], 1) == Some("a")
pairs.find_first([Pair("a", 1), Pair("b", 2), Pair("c", 1)], 1) == Some("a")

find_last(self: Pairs<key, value>, v: value) -> Option<key>

Finds the last key in the alist associated with a given value, if any.

pairs.find_last([], 1) == None
pairs.find_last([Pair("a", 1)], 1) == Some("a")
pairs.find_last([Pair("a", 1), Pair("b", 2)], 1) == Some("a")
pairs.find_last([Pair("a", 1), Pair("b", 2), Pair("c", 1)], 1) == Some("c")

foldl(
  self: Pairs<key, value>,
  zero: result,
  with: fn(key, value, result) -> result,
) -> result

Fold over the key-value pairs in a pairs. The fold direction follows keys in ascending order and is done from left-to-right.

let fixture = [
  Pair(1, 100),
  Pair(2, 200),
  Pair(3, 300),
]

pairs.foldl(fixture, 0, fn(k, v, result) { k * v + result }) == 1400

foldr(
  self: Pairs<key, value>,
  zero: result,
  with: fn(key, value, result) -> result,
) -> result

Fold over the key-value pairs in a Pairs. The fold direction follows the order of elements in the Pairs and is done from right-to-left.

let fixture = [
  Pair(1, 100),
  Pair(2, 200),
  Pair(3, 300),
]

pairs.foldr(fixture, 0, fn(k, v, result) { k * v + result }) == 1400

get_all(self: Pairs<key, value>, key: key) -> List<value>

Get all values in the alist associated with a given key.

pairs.get_all([], "a") == []
pairs.get_all([Pair("a", 1)], "a") == [1]
pairs.get_all([Pair("a", 1), Pair("b", 2)], "a") == [1]
pairs.get_all([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == [1, 3]

get_first(self: Pairs<key, value>, key: key) -> Option<value>

Get the value in the alist by its key. If multiple values with the same key exist, only the first one is returned.

pairs.get_first([], "a") == None
pairs.get_first([Pair("a", 1)], "a") == Some(1)
pairs.get_first([Pair("a", 1), Pair("b", 2)], "a") == Some(1)
pairs.get_first([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == Some(1)

get_last(self: Pairs<key, value>, key: key) -> Option<value>

Get the value in the alist by its key. If multiple values with the same key exist, only the last one is returned.

pairs.get_last([], "a") == None
pairs.get_last([Pair("a", 1)], "a") == Some(1)
pairs.get_last([Pair("a", 1), Pair("b", 2)], "a") == Some(1)
pairs.get_last([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == Some(3)

has_key(self: Pairs<key, value>, k: key) -> Bool

Check if a key exists in the pairs.

pairs.has_key([], "a") == False
pairs.has_key([Pair("a", 1)], "a") == True
pairs.has_key([Pair("a", 1), Pair("b", 2)], "a") == True
pairs.has_key([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == True

keys(self: Pairs<key, value>) -> List<key>

Extract all the keys present in a given Pairs.

pairs.keys([]) == []
pairs.keys([Pair("a", 1)]) == ["a"]
pairs.keys([Pair("a", 1), Pair("b", 2)]) == ["a", "b"]
pairs.keys([Pair("a", 1), Pair("b", 2), Pair("a", 3)]) == ["a", "b", "a"]

map(
  self: Pairs<key, value>,
  with: fn(key, value) -> result,
) -> Pairs<key, result>

Apply a function to all key-value pairs in a alist, replacing the values.

let fixture = [Pair("a", 100), Pair("b", 200)]

pairs.map(fixture, fn(_k, v) { v * 2 }) == [Pair("a", 200), Pair("b", 400)]

remove_all(self: Pairs<key, value>, key: key) -> Pairs<key, value>

Remove all key-value pairs matching the key from the Pairs. If the key is not found, no changes are made.

pairs.remove_all([], "a") == []
pairs.remove_all([Pair("a", 1)], "a") == []
pairs.remove_all([Pair("a", 1), Pair("b", 2)], "a") == [Pair("b", 2)]
pairs.remove_all([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == [Pair("b", 2)]

remove_first(self: Pairs<key, value>, key: key) -> Pairs<key, value>

Remove a single key-value pair from the Pairs. If the key is not found, no changes are made. Duplicate keys are not removed. Only the first key found is removed.

pairs.remove_first([], "a") == []
pairs.remove_first([Pair("a", 1)], "a") == []
pairs.remove_first([Pair("a", 1), Pair("b", 2)], "a") == [Pair("b", 2)]
pairs.remove_first([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == [Pair("b", 2), Pair("a", 3)]

remove_last(self: Pairs<key, value>, key: key) -> Pairs<key, value>

Remove a single key-value pair from the Pairs. If the key is not found, no changes are made. Duplicate keys are not removed. Only the last key found is removed.

pairs.remove_last([], "a") == []
pairs.remove_last([Pair("a", 1)], "a") == []
pairs.remove_last([Pair("a", 1), Pair("b", 2)], "a") == [Pair("b", 2)]
pairs.remove_last([Pair("a", 1), Pair("b", 2), Pair("a", 3)], "a") == [Pair("a", 1), Pair("b", 2)]

values(self: Pairs<key, value>) -> List<value>

Extract all the values present in a given Pairs.

pairs.values([]) == []
pairs.values([Pair("a", 1)]) == [1]
pairs.values([Pair("a", 1), Pair("b", 2)]) == [1, 2]
pairs.values([Pair("a", 1), Pair("b", 2), Pair("a", 3)]) == [1, 2, 3]
Search Document