lib: implement `compare`, `splitByAndCompare`, and `compareLists`

Changed files
+64 -3
lib
+4 -3
lib/default.nix
···
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;
···
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
+24
lib/lists.nix
···
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:
+36
lib/trivial.nix
···
*/
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);