Skip to content

Commit

Permalink
Merge master into staging-next
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions[bot] authored Apr 19, 2024
2 parents fec763e + a3a4f77 commit 8be479c
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 25 deletions.
48 changes: 43 additions & 5 deletions lib/attrsets.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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; }
Expand All @@ -904,7 +904,7 @@ rec {
:::
*/
cartesianProductOfSets =
cartesianProduct =
attrsOfLists:
foldl' (listOfAttrs: attrName:
concatMap (attrs:
Expand All @@ -913,6 +913,40 @@ rec {
) [{}] (attrNames attrsOfLists);


/**
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`.
Expand Down Expand Up @@ -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;
}
4 changes: 2 additions & 2 deletions lib/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 19 additions & 3 deletions lib/lists.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
50 changes: 35 additions & 15 deletions lib/tests/misc.nix
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ let
boolToString
callPackagesWith
callPackageWith
cartesianProductOfSets
cartesianProduct
cli
composeExtensions
composeManyExtensions
Expand Down Expand Up @@ -71,10 +71,10 @@ let
makeIncludePath
makeOverridable
mapAttrs
mapCartesianProduct
matchAttrs
mergeAttrs
meta
mkOption
mod
nameValuePair
optionalDrvAttr
Expand Down Expand Up @@ -117,7 +117,6 @@ let
expr = (builtins.tryEval expr).success;
expected = true;
};
testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr);

testSanitizeDerivationName = { name, expected }:
let
Expand Down Expand Up @@ -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";
Expand All @@ -1429,7 +1428,7 @@ runTests {
there
test'';
};
expected = rec {
expected = {
list = ''
[
3
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1686,30 +1682,30 @@ 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; }
];
};

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 ];
Expand Down Expand Up @@ -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" ];
Expand Down

0 comments on commit 8be479c

Please sign in to comment.