about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2024-04-19 12:01:13 +0000
committerGitHub <noreply@github.com>2024-04-19 12:01:13 +0000
commit11b87cbe5984013635d05c44e9908d12339470d6 (patch)
treeddd338d8bb7df566c58ec9b8e7f8cffb28a672c8 /lib
parentda03c8fb0a127580ccb95d4430f8f1f67a89cf38 (diff)
parent193037db72bfe3ce4a24a9d7fe99a2c4160f40be (diff)
Merge master into staging-next
Diffstat (limited to 'lib')
-rw-r--r--lib/attrsets.nix48
-rw-r--r--lib/default.nix4
-rw-r--r--lib/lists.nix22
-rw-r--r--lib/tests/misc.nix50
4 files changed, 99 insertions, 25 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 49d311ed37b39..83f8d0f34186e 100644
--- a/lib/attrsets.nix
+++ b/lib/attrsets.nix
@@ -5,7 +5,7 @@
 
 let
   inherit (builtins) head length;
-  inherit (lib.trivial) mergeAttrs warn;
+  inherit (lib.trivial) isInOldestRelease mergeAttrs warn warnIf;
   inherit (lib.strings) concatStringsSep concatMapStringsSep escapeNixIdentifier sanitizeDerivationName;
   inherit (lib.lists) foldr foldl' concatMap elemAt all partition groupBy take foldl;
 in
@@ -885,15 +885,15 @@ rec {
     # Type
 
     ```
-    cartesianProductOfSets :: AttrSet -> [AttrSet]
+    cartesianProduct :: AttrSet -> [AttrSet]
     ```
 
     # Examples
     :::{.example}
-    ## `lib.attrsets.cartesianProductOfSets` usage example
+    ## `lib.attrsets.cartesianProduct` usage example
 
     ```nix
-    cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
+    cartesianProduct { a = [ 1 2 ]; b = [ 10 20 ]; }
     => [
          { a = 1; b = 10; }
          { a = 1; b = 20; }
@@ -904,7 +904,7 @@ rec {
 
     :::
   */
-  cartesianProductOfSets =
+  cartesianProduct =
     attrsOfLists:
     foldl' (listOfAttrs: attrName:
       concatMap (attrs:
@@ -914,6 +914,40 @@ rec {
 
 
   /**
+    Return the result of function f applied to the cartesian product of attribute set value combinations.
+    Equivalent to using cartesianProduct followed by map.
+
+    # Inputs
+
+    `f`
+
+    : A function, given an attribute set, it returns a new value.
+
+    `attrsOfLists`
+
+    : Attribute set with attributes that are lists of values
+
+    # Type
+
+    ```
+    mapCartesianProduct :: (AttrSet -> a) -> AttrSet -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapCartesianProduct` usage example
+
+    ```nix
+    mapCartesianProduct ({a, b}: "${a}-${b}") { a = [ "1" "2" ]; b = [ "3" "4" ]; }
+    => [ "1-3" "1-4" "2-3" "2-4" ]
+    ```
+
+    :::
+
+  */
+  mapCartesianProduct = f: attrsOfLists: map f (cartesianProduct attrsOfLists);
+
+  /**
     Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
 
 
@@ -1999,4 +2033,8 @@ rec {
   # DEPRECATED
   zip = warn
     "lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;
+
+  # DEPRECATED
+  cartesianProductOfSets = warnIf (isInOldestRelease 2405)
+    "lib.cartesianProductOfSets is a deprecated alias of lib.cartesianProduct." cartesianProduct;
 }
diff --git a/lib/default.nix b/lib/default.nix
index 21e4bab2b942b..486d412fbb6fd 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -86,8 +86,8 @@ let
       zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
       recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput
       getBin getLib getDev getMan chooseDevOutputs zipWithNames zip
-      recurseIntoAttrs dontRecurseIntoAttrs cartesianProductOfSets
-      updateManyAttrsByPath;
+      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
       optional optionals toList range replicate partition zipListsWith zipLists
diff --git a/lib/lists.nix b/lib/lists.nix
index c162f921280d2..28fa277b22b1f 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -1688,16 +1688,32 @@ rec {
     ## `lib.lists.crossLists` usage example
 
     ```nix
-    crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
+    crossLists (x: y: "${toString x}${toString y}") [[1 2] [3 4]]
     => [ "13" "14" "23" "24" ]
     ```
 
+    The following function call is equivalent to the one deprecated above:
+
+    ```nix
+    mapCartesianProduct (x: "${toString x.a}${toString x.b}") { a = [1 2]; b = [3 4]; }
+    => [ "13" "14" "23" "24" ]
+    ```
     :::
   */
   crossLists = warn
-    "lib.crossLists is deprecated, use lib.cartesianProductOfSets instead."
-    (f: foldl (fs: args: concatMap (f: map f args) fs) [f]);
+    ''lib.crossLists is deprecated, use lib.mapCartesianProduct instead.
 
+    For example, the following function call:
+
+    nix-repl> lib.crossLists (x: y: x+y) [[1 2] [3 4]]
+    [ 4 5 5 6 ]
+
+    Can now be replaced by the following one:
+
+    nix-repl> lib.mapCartesianProduct ({x,y}: x+y) { x = [1 2]; y = [3 4]; }
+    [ 4 5 5 6 ]
+    ''
+    (f: foldl (fs: args: concatMap (f: map f args) fs) [f]);
 
   /**
     Remove duplicate elements from the `list`. O(n^2) complexity.
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index accceb4ddf9c1..cf4a185c14689 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -33,7 +33,7 @@ let
     boolToString
     callPackagesWith
     callPackageWith
-    cartesianProductOfSets
+    cartesianProduct
     cli
     composeExtensions
     composeManyExtensions
@@ -71,10 +71,10 @@ let
     makeIncludePath
     makeOverridable
     mapAttrs
+    mapCartesianProduct
     matchAttrs
     mergeAttrs
     meta
-    mkOption
     mod
     nameValuePair
     optionalDrvAttr
@@ -117,7 +117,6 @@ let
     expr = (builtins.tryEval expr).success;
     expected = true;
   };
-  testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr);
 
   testSanitizeDerivationName = { name, expected }:
   let
@@ -1415,7 +1414,7 @@ runTests {
     };
 
   testToPrettyMultiline = {
-    expr = mapAttrs (const (generators.toPretty { })) rec {
+    expr = mapAttrs (const (generators.toPretty { })) {
       list = [ 3 4 [ false ] ];
       attrs = { foo = null; bar.foo = "baz"; };
       newlinestring = "\n";
@@ -1429,7 +1428,7 @@ runTests {
         there
         test'';
     };
-    expected = rec {
+    expected = {
       list = ''
         [
           3
@@ -1467,13 +1466,10 @@ runTests {
     expected  = "«foo»";
   };
 
-  testToPlist =
-    let
-      deriv = derivation { name = "test"; builder = "/bin/sh"; system = "aarch64-linux"; };
-    in {
+  testToPlist = {
     expr = mapAttrs (const (generators.toPlist { })) {
       value = {
-        nested.values = rec {
+        nested.values = {
           int = 42;
           float = 0.1337;
           bool = true;
@@ -1686,17 +1682,17 @@ runTests {
   };
 
   testCartesianProductOfEmptySet = {
-    expr = cartesianProductOfSets {};
+    expr = cartesianProduct {};
     expected = [ {} ];
   };
 
   testCartesianProductOfOneSet = {
-    expr = cartesianProductOfSets { a = [ 1 2 3 ]; };
+    expr = cartesianProduct { a = [ 1 2 3 ]; };
     expected = [ { a = 1; } { a = 2; } { a = 3; } ];
   };
 
   testCartesianProductOfTwoSets = {
-    expr = cartesianProductOfSets { a = [ 1 ]; b = [ 10 20 ]; };
+    expr = cartesianProduct { a = [ 1 ]; b = [ 10 20 ]; };
     expected = [
       { a = 1; b = 10; }
       { a = 1; b = 20; }
@@ -1704,12 +1700,12 @@ runTests {
   };
 
   testCartesianProductOfTwoSetsWithOneEmpty = {
-    expr = cartesianProductOfSets { a = [ ]; b = [ 10 20 ]; };
+    expr = cartesianProduct { a = [ ]; b = [ 10 20 ]; };
     expected = [ ];
   };
 
   testCartesianProductOfThreeSets = {
-    expr = cartesianProductOfSets {
+    expr = cartesianProduct {
       a = [   1   2   3 ];
       b = [  10  20  30 ];
       c = [ 100 200 300 ];
@@ -1753,6 +1749,30 @@ runTests {
     ];
   };
 
+  testMapCartesianProductOfOneSet = {
+    expr = mapCartesianProduct ({a}: a * 2) { a = [ 1 2 3 ]; };
+    expected = [ 2 4 6 ];
+  };
+
+  testMapCartesianProductOfTwoSets = {
+    expr = mapCartesianProduct ({a,b}: a + b) { a = [ 1 ]; b = [ 10 20 ]; };
+    expected = [ 11 21 ];
+  };
+
+  testMapCartesianProcutOfTwoSetsWithOneEmpty = {
+    expr = mapCartesianProduct (x: x.a + x.b) { a = [ ]; b = [ 10 20 ]; };
+    expected = [ ];
+  };
+
+  testMapCartesianProductOfThreeSets = {
+    expr = mapCartesianProduct ({a,b,c}: a + b + c) {
+      a = [ 1 2 3 ];
+      b = [ 10 20 30 ];
+      c = [ 100 200 300 ];
+    };
+    expected = [ 111 211 311 121 221 321 131 231 331 112 212 312 122 222 322 132 232 332 113 213 313 123 223 323 133 233 333 ];
+  };
+
   # The example from the showAttrPath documentation
   testShowAttrPathExample = {
     expr = showAttrPath [ "foo" "10" "bar" ];