about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/default.nix4
-rw-r--r--lib/deprecated/README.md11
-rw-r--r--lib/deprecated/misc.nix (renamed from lib/deprecated.nix)0
-rw-r--r--lib/lists.nix50
-rw-r--r--lib/tests/misc.nix27
5 files changed, 89 insertions, 3 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 486d412fbb6fd..d5d47defb8e64 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -47,7 +47,7 @@ let
     # misc
     asserts = callLibs ./asserts.nix;
     debug = callLibs ./debug.nix;
-    misc = callLibs ./deprecated.nix;
+    misc = callLibs ./deprecated/misc.nix;
 
     # domain-specific
     fetchers = callLibs ./fetchers.nix;
@@ -89,7 +89,7 @@ let
       recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets
       mapCartesianProduct updateManyAttrsByPath;
     inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
-      concatMap flatten remove findSingle findFirst any all count
+      ifilter0 concatMap flatten remove findSingle findFirst any all count
       optional optionals toList range replicate partition zipListsWith zipLists
       reverseList listDfs toposort sort sortOn naturalSort compareLists take
       drop sublist last init crossLists unique allUnique intersectLists
diff --git a/lib/deprecated/README.md b/lib/deprecated/README.md
new file mode 100644
index 0000000000000..afeb34d449f56
--- /dev/null
+++ b/lib/deprecated/README.md
@@ -0,0 +1,11 @@
+
+# lib/deprecated
+
+Do not add any new functions to this directory.
+
+This directory contains the `lib.misc` sublibrary, which - as a location - is deprecated.
+Furthermore, some of the functions inside are of *dubious* utility, and should perhaps be avoided,
+while some functions *may still be needed*.
+
+This directory does not play a role in the deprecation process for library functions.
+They should be deprecated in place, by putting a `lib.warn` or `lib.warnIf` call around the function.
diff --git a/lib/deprecated.nix b/lib/deprecated/misc.nix
index d556bccbec0bc..d556bccbec0bc 100644
--- a/lib/deprecated.nix
+++ b/lib/deprecated/misc.nix
diff --git a/lib/lists.nix b/lib/lists.nix
index 28fa277b22b1f..ca436d7a9c94b 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -4,7 +4,7 @@
 { lib }:
 let
   inherit (lib.strings) toInt;
-  inherit (lib.trivial) compare min id warn;
+  inherit (lib.trivial) compare min id warn pipe;
   inherit (lib.attrsets) mapAttrs;
 in
 rec {
@@ -334,6 +334,54 @@ rec {
   imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list);
 
   /**
+    Filter a list for elements that satisfy a predicate function.
+    The predicate function is called with both the index and value for each element.
+    It must return `true`/`false` to include/exclude a given element in the result.
+    This function is strict in the result of the predicate function for each element.
+    This function has O(n) complexity.
+
+    Also see [`builtins.filter`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-filter) (available as `lib.lists.filter`),
+    which can be used instead when the index isn't needed.
+
+    # Inputs
+
+    `ipred`
+
+    : The predicate function, it takes two arguments:
+      - 1. (int): the index of the element.
+      - 2. (a): the value of the element.
+
+      It must return `true`/`false` to include/exclude a given element from the result.
+
+    `list`
+
+    : The list to filter using the predicate.
+
+    # Type
+    ```
+    ifilter0 :: (int -> a -> bool) -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.ifilter0` usage example
+
+    ```nix
+    ifilter0 (i: v: i == 0 || v > 2) [ 1 2 3 ]
+    => [ 1 3 ]
+    ```
+    :::
+  */
+  ifilter0 =
+    ipred:
+    input:
+    map (idx: elemAt input idx) (
+      filter (idx: ipred idx (elemAt input idx)) (
+        genList (x: x) (length input)
+      )
+    );
+
+  /**
     Map and concatenate the result.
 
     # Type
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index cf4a185c14689..6774939023d20 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -63,8 +63,10 @@ let
     hasAttrByPath
     hasInfix
     id
+    ifilter0
     isStorePath
     lazyDerivation
+    length
     lists
     listToAttrs
     makeExtensible
@@ -651,6 +653,31 @@ runTests {
     expected = ["b" "c"];
   };
 
+  testIfilter0Example = {
+    expr = ifilter0 (i: v: i == 0 || v > 2) [ 1 2 3 ];
+    expected = [ 1 3 ];
+  };
+  testIfilter0Empty = {
+    expr = ifilter0 (i: v: abort "shouldn't be evaluated!") [ ];
+    expected = [ ];
+  };
+  testIfilter0IndexOnly = {
+    expr = length (ifilter0 (i: v: mod i 2 == 0) [ (throw "0") (throw "1") (throw "2") (throw "3")]);
+    expected = 2;
+  };
+  testIfilter0All = {
+    expr = ifilter0 (i: v: true) [ 10 11 12 13 14 15 ];
+    expected = [ 10 11 12 13 14 15 ];
+  };
+  testIfilter0First = {
+    expr = ifilter0 (i: v: i == 0) [ 10 11 12 13 14 15 ];
+    expected = [ 10 ];
+  };
+  testIfilter0Last = {
+    expr = ifilter0 (i: v: i == 5) [ 10 11 12 13 14 15 ];
+    expected = [ 15 ];
+  };
+
   testFold =
     let
       f = op: fold: fold op 0 (range 0 100);