diff options
author | Silvan Mosberger <silvan.mosberger@tweag.io> | 2023-07-19 16:44:11 +0200 |
---|---|---|
committer | Silvan Mosberger <silvan.mosberger@tweag.io> | 2023-07-19 17:35:28 +0200 |
commit | 53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3 (patch) | |
tree | 0b1bf8d1b2c9ec8163409aa4b4c9f569e877a8b8 /lib | |
parent | a4f7840e1813bc389995083fac2b3bcd0ca6823d (diff) | |
download | nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.tar nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.tar.gz nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.tar.bz2 nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.tar.lz nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.tar.xz nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.tar.zst nixpkgs-53dcfd24ad71bb1a26c9d17cbd2af1f83a2da7a3.zip |
lib.lists.findFirstIndex: init
Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/lists.nix | 42 | ||||
-rw-r--r-- | lib/tests/misc.nix | 50 |
2 files changed, 64 insertions, 28 deletions
diff --git a/lib/lists.nix b/lib/lists.nix index 5d9af0cf711..c3e889644b3 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -180,18 +180,18 @@ rec { else if len != 1 then multiple else head found; - /* Find the first element in the list matching the specified + /* Find the first index in the list matching the specified predicate or return `default` if no such element exists. - Type: findFirst :: (a -> bool) -> a -> [a] -> a + Type: findFirstIndex :: (a -> Bool) -> b -> [a] -> (Int | b) Example: - findFirst (x: x > 3) 7 [ 1 6 4 ] - => 6 - findFirst (x: x > 9) 7 [ 1 6 4 ] - => 7 + findFirstIndex (x: x > 3) null [ 0 6 4 ] + => 1 + findFirstIndex (x: x > 9) null [ 0 6 4 ] + => null */ - findFirst = + findFirstIndex = # Predicate pred: # Default value to return @@ -229,7 +229,33 @@ rec { if resultIndex < 0 then default else - elemAt list resultIndex; + resultIndex; + + /* Find the first element in the list matching the specified + predicate or return `default` if no such element exists. + + Type: findFirst :: (a -> bool) -> a -> [a] -> a + + Example: + findFirst (x: x > 3) 7 [ 1 6 4 ] + => 6 + findFirst (x: x > 9) 7 [ 1 6 4 ] + => 7 + */ + findFirst = + # Predicate + pred: + # Default value to return + default: + # Input list + list: + let + index = findFirstIndex pred null list; + in + if index == null then + default + else + elemAt list index; /* Return true if function `pred` returns true for at least one element of `list`. diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index ce980436c1b..dfa6a94ee48 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -518,45 +518,55 @@ runTests { expected = false; }; - testFindFirstExample1 = { - expr = findFirst (x: x > 3) 7 [ 1 6 4 ]; - expected = 6; + testFindFirstIndexExample1 = { + expr = lists.findFirstIndex (x: x > 3) (abort "index found, so a default must not be evaluated") [ 1 6 4 ]; + expected = 1; }; - testFindFirstExample2 = { - expr = findFirst (x: x > 9) 7 [ 1 6 4 ]; - expected = 7; + testFindFirstIndexExample2 = { + expr = lists.findFirstIndex (x: x > 9) "a very specific default" [ 1 6 4 ]; + expected = "a very specific default"; }; - testFindFirstEmpty = { - expr = findFirst (abort "when the list is empty, the predicate is not needed") null []; + testFindFirstIndexEmpty = { + expr = lists.findFirstIndex (abort "when the list is empty, the predicate is not needed") null []; expected = null; }; - testFindFirstSingleMatch = { - expr = findFirst (x: x == 5) null [ 5 ]; - expected = 5; + testFindFirstIndexSingleMatch = { + expr = lists.findFirstIndex (x: x == 5) null [ 5 ]; + expected = 0; }; - testFindFirstSingleDefault = { - expr = findFirst (x: false) null [ (abort "if the predicate doesn't access the value, it must not be evaluated") ]; + testFindFirstIndexSingleDefault = { + expr = lists.findFirstIndex (x: false) null [ (abort "if the predicate doesn't access the value, it must not be evaluated") ]; expected = null; }; - testFindFirstNone = { - expr = builtins.tryEval (findFirst (x: x == 2) null [ 1 (throw "the last element must be evaluated when there's no match") ]); + testFindFirstIndexNone = { + expr = builtins.tryEval (lists.findFirstIndex (x: x == 2) null [ 1 (throw "the last element must be evaluated when there's no match") ]); expected = { success = false; value = false; }; }; # Makes sure that the implementation doesn't cause a stack overflow - testFindFirstBig = { - expr = findFirst (x: x == 1000000) null (range 0 1000000); + testFindFirstIndexBig = { + expr = lists.findFirstIndex (x: x == 1000000) null (range 0 1000000); expected = 1000000; }; - testFindFirstLazy = { - expr = findFirst (x: x == 1) 7 [ 1 (abort "list elements after the match must not be evaluated") ]; - expected = 1; + testFindFirstIndexLazy = { + expr = lists.findFirstIndex (x: x == 1) null [ 1 (abort "list elements after the match must not be evaluated") ]; + expected = 0; + }; + + testFindFirstExample1 = { + expr = lists.findFirst (x: x > 3) 7 [ 1 6 4 ]; + expected = 6; + }; + + testFindFirstExample2 = { + expr = lists.findFirst (x: x > 9) 7 [ 1 6 4 ]; + expected = 7; }; # ATTRSETS |