lib/attrsets: introduce mapCartesianProduct

This commit is contained in:
Gabriel Volpe 2024-04-15 19:16:15 +02:00
parent 10517cf9ab
commit fe2bead78b
No known key found for this signature in database
GPG key ID: 121D4302A64B2261
3 changed files with 60 additions and 1 deletions

View file

@ -913,6 +913,40 @@ rec {
) [{}] (attrNames attrsOfLists); ) [{}] (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`. Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.

View file

@ -87,7 +87,7 @@ let
recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput
getBin getLib getDev getMan chooseDevOutputs zipWithNames zip getBin getLib getDev getMan chooseDevOutputs zipWithNames zip
recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets
updateManyAttrsByPath; mapCartesianProduct updateManyAttrsByPath;
inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1 inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1
concatMap flatten remove findSingle findFirst any all count concatMap flatten remove findSingle findFirst any all count
optional optionals toList range replicate partition zipListsWith zipLists optional optionals toList range replicate partition zipListsWith zipLists

View file

@ -71,6 +71,7 @@ let
makeIncludePath makeIncludePath
makeOverridable makeOverridable
mapAttrs mapAttrs
mapCartesianProduct
matchAttrs matchAttrs
mergeAttrs mergeAttrs
meta meta
@ -1753,6 +1754,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 # The example from the showAttrPath documentation
testShowAttrPathExample = { testShowAttrPathExample = {
expr = showAttrPath [ "foo" "10" "bar" ]; expr = showAttrPath [ "foo" "10" "bar" ];