From bc8fbc25723b05e0f909faa6589641867200775b Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Fri, 14 Jul 2023 18:18:48 +0200 Subject: [PATCH 1/2] lib.lists.hasPrefix: init --- lib/lists.nix | 15 +++++++++++++++ lib/tests/misc.nix | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/lists.nix b/lib/lists.nix index 5d9af0cf7114..e12bc9048ef1 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -612,6 +612,21 @@ rec { # Input list list: sublist count (length list) list; + /* Whether the first list is a prefix of the second list. + + Type: hasPrefix :: [a] -> [a] -> bool + + Example: + hasPrefix [ 1 2 ] [ 1 2 3 4 ] + => true + hasPrefix [ 0 1 ] [ 1 2 3 4 ] + => false + */ + hasPrefix = + list1: + list2: + take (length list1) list2 == list1; + /* Return a list consisting of at most `count` elements of `list`, starting at index `start`. diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index ce980436c1bc..5c824a066e16 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -480,6 +480,27 @@ runTests { ([ 1 2 3 ] == (take 4 [ 1 2 3 ])) ]; + testListHasPrefixExample1 = { + expr = lists.hasPrefix [ 1 2 ] [ 1 2 3 4 ]; + expected = true; + }; + testListHasPrefixExample2 = { + expr = lists.hasPrefix [ 0 1 ] [ 1 2 3 4 ]; + expected = false; + }; + testListHasPrefixLazy = { + expr = lists.hasPrefix [ 1 ] [ 1 (abort "lib.lists.hasPrefix is not lazy") ]; + expected = true; + }; + testListHasPrefixEmptyPrefix = { + expr = lists.hasPrefix [ ] [ 1 2 ]; + expected = true; + }; + testListHasPrefixEmptyList = { + expr = lists.hasPrefix [ 1 2 ] [ ]; + expected = false; + }; + testFoldAttrs = { expr = foldAttrs (n: a: [n] ++ a) [] [ { a = 2; b = 7; } From 9fdc0bb2bfa2d1dd631bb39f3b9e7cfec16bcd54 Mon Sep 17 00:00:00 2001 From: Silvan Mosberger Date: Fri, 14 Jul 2023 18:28:38 +0200 Subject: [PATCH 2/2] lib.lists.removePrefix: init --- lib/lists.nix | 19 +++++++++++++++++++ lib/tests/misc.nix | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/lib/lists.nix b/lib/lists.nix index e12bc9048ef1..c9821819821e 100644 --- a/lib/lists.nix +++ b/lib/lists.nix @@ -627,6 +627,25 @@ rec { list2: take (length list1) list2 == list1; + /* Remove the first list as a prefix from the second list. + Error if the first list isn't a prefix of the second list. + + Type: removePrefix :: [a] -> [a] -> [a] + + Example: + removePrefix [ 1 2 ] [ 1 2 3 4 ] + => [ 3 4 ] + removePrefix [ 0 1 ] [ 1 2 3 4 ] + => + */ + removePrefix = + list1: + list2: + if hasPrefix list1 list2 then + drop (length list1) list2 + else + throw "lib.lists.removePrefix: First argument is not a list prefix of the second argument"; + /* Return a list consisting of at most `count` elements of `list`, starting at index `start`. diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 5c824a066e16..4f7035a53f5b 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -501,6 +501,23 @@ runTests { expected = false; }; + testListRemovePrefixExample1 = { + expr = lists.removePrefix [ 1 2 ] [ 1 2 3 4 ]; + expected = [ 3 4 ]; + }; + testListRemovePrefixExample2 = { + expr = (builtins.tryEval (lists.removePrefix [ 0 1 ] [ 1 2 3 4 ])).success; + expected = false; + }; + testListRemovePrefixEmptyPrefix = { + expr = lists.removePrefix [ ] [ 1 2 ]; + expected = [ 1 2 ]; + }; + testListRemovePrefixEmptyList = { + expr = (builtins.tryEval (lists.removePrefix [ 1 2 ] [ ])).success; + expected = false; + }; + testFoldAttrs = { expr = foldAttrs (n: a: [n] ++ a) [] [ { a = 2; b = 7; }