summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Malakhovski <oxij@oxij.org>2017-12-07 21:26:30 +0000
committerJan Malakhovski <oxij@oxij.org>2018-02-09 19:51:05 +0000
commitee3220440da59e39154b520353a3d03a1abf3405 (patch)
treeaa3bf8018184d395869ffd2a32dd97632c2b100f
parent2341c81427420be95cd9f8640e3e96e3e317c645 (diff)
lib: implement `compare`, `splitByAndCompare`, and `compareLists`
-rw-r--r--lib/default.nix7
-rw-r--r--lib/lists.nix24
-rw-r--r--lib/trivial.nix36
3 files changed, 64 insertions, 3 deletions
diff --git a/lib/default.nix b/lib/default.nix
index 97d7c10192a7..77cfa712557c 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -56,7 +56,8 @@ let
replaceStrings seq stringLength sub substring tail;
inherit (trivial) id const concat or and boolToString mergeAttrs
flip mapNullable inNixShell min max importJSON warn info
- nixpkgsVersion mod functionArgs setFunctionArgs isFunction;
+ nixpkgsVersion mod compare splitByAndCompare
+ functionArgs setFunctionArgs isFunction;
inherit (fixedPoints) fix fix' extends composeExtensions
makeExtensible makeExtensibleWithCustomName;
@@ -71,8 +72,8 @@ let
inherit (lists) singleton foldr fold foldl foldl' imap0 imap1
concatMap flatten remove findSingle findFirst any all count
optional optionals toList range partition zipListsWith zipLists
- reverseList listDfs toposort sort take drop sublist last init
- crossLists unique intersectLists subtractLists
+ reverseList listDfs toposort sort compareLists take drop sublist
+ last init crossLists unique intersectLists subtractLists
mutuallyExclusive;
inherit (strings) concatStrings concatMapStrings concatImapStrings
intersperse concatStringsSep concatMapStringsSep
diff --git a/lib/lists.nix b/lib/lists.nix
index 8f67c6bb0ca3..f7e09040a5aa 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -385,6 +385,30 @@ rec {
if len < 2 then list
else (sort strictLess pivot.left) ++ [ first ] ++ (sort strictLess pivot.right));
+ /* Compare two lists element-by-element.
+
+ Example:
+ compareLists compare [] []
+ => 0
+ compareLists compare [] [ "a" ]
+ => -1
+ compareLists compare [ "a" ] []
+ => 1
+ compareLists compare [ "a" "b" ] [ "a" "c" ]
+ => 1
+ */
+ compareLists = cmp: a: b:
+ if a == []
+ then if b == []
+ then 0
+ else -1
+ else if b == []
+ then 1
+ else let rel = cmp (head a) (head b); in
+ if rel == 0
+ then compareLists cmp (tail a) (tail b)
+ else rel;
+
/* Return the first (at most) N elements of a list.
Example:
diff --git a/lib/trivial.nix b/lib/trivial.nix
index d8d51298143e..a928e1dbca98 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -81,6 +81,42 @@ rec {
*/
mod = base: int: base - (int * (builtins.div base int));
+ /* C-style comparisons
+
+ a < b, compare a b => -1
+ a == b, compare a b => 0
+ a > b, compare a b => 1
+ */
+ compare = a: b:
+ if a < b
+ then -1
+ else if a > b
+ then 1
+ else 0;
+
+ /* Split type into two subtypes by predicate `p`, take all elements
+ of the first subtype to be less than all the elements of the
+ second subtype, compare elements of a single subtype with `yes`
+ and `no` respectively.
+
+ Example:
+
+ let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
+
+ cmp "a" "z" => -1
+ cmp "fooa" "fooz" => -1
+
+ cmp "f" "a" => 1
+ cmp "fooa" "a" => -1
+ # while
+ compare "fooa" "a" => 1
+
+ */
+ splitByAndCompare = p: yes: no: a: b:
+ if p a
+ then if p b then yes a b else -1
+ else if p b then 1 else no a b;
+
/* Reads a JSON file. */
importJSON = path:
builtins.fromJSON (builtins.readFile path);