nt/nt/primitives/bootstrap/prim/list.nix
2026-01-28 12:55:12 +10:00

85 lines
2 KiB
Nix

{...}: let
inherit
(builtins)
all
elem
elemAt
foldl'
genList
length
;
in rec {
contains = sub: list: all (x: elem x list) sub;
sublist = start: count: list: let
len = length list;
in
genList (n: elemAt list (n + start)) (
if start >= len
then 0
else if start + count > len
then len - start
else count
);
take = count: sublist 0 count;
init = list:
assert (list != []) || throw "lists.init: list must not be empty!";
take (length list - 1) list;
last = list:
assert (list != []) || throw "lists.last: list must not be empty!";
elemAt list (length list - 1);
# REF: pkgs.lib.lists.reverseList
reverse = xs: let
l = length xs;
in
genList (n: elemAt xs (l - n - 1)) l;
# REF: pkgs.lib.lists.foldr
foldr = op: nul: list: let
len = length list;
fold' = n:
if n == len
then nul
else op (elemAt list n) (fold' (n + 1));
in
fold' 0;
# REF: pkgs.lib.lists.findFirstIndex [MODIFIED]
firstIndexWhere = pred: default: list: let
resultIndex =
foldl' (
index: el:
if index < 0
then
# No match yet before the current index, we need to check the element
if pred el
then
# We have a match! Turn it into the actual index to prevent future iterations from modifying it
-index - 1
else
# Still no match, update the index to the next element (we're counting down, so minus one)
index - 1
else
# There's already a match, propagate the index without evaluating anything
index
) (-1)
list;
in
if resultIndex < 0
then default
else resultIndex;
firstIndexOf = x: firstIndexWhere (el: el == x);
# WARNING: returns `default` in the edgecase `pred el && el == null`
firstWhere = pred: default: list: let
index = firstIndexWhere pred null list;
in
if index == null
then default
else elemAt list index;
}