From 228621e42dc43f936b66e0ed042c90c511aa0535 Mon Sep 17 00:00:00 2001 From: Gabriel Volpe Date: Mon, 15 Apr 2024 19:03:54 +0200 Subject: lib/attrsets: rename cartesianProductOfSets to cartesianProduct --- lib/attrsets.nix | 14 +++++++++----- lib/default.nix | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/attrsets.nix b/lib/attrsets.nix index 49d311ed37b3..5c4f735b63da 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: @@ -1999,4 +1999,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 c77ce88cc440..97a81d4763bf 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -86,7 +86,7 @@ let zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput getBin getLib getDev getMan chooseDevOutputs zipWithNames zip - recurseIntoAttrs dontRecurseIntoAttrs cartesianProductOfSets + recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets updateManyAttrsByPath; inherit (self.lists) singleton forEach foldr fold foldl foldl' imap0 imap1 concatMap flatten remove findSingle findFirst any all count -- cgit 1.4.1 From 10517cf9abe8d54c66b1dd5fb18fc4b03750037f Mon Sep 17 00:00:00 2001 From: Gabriel Volpe Date: Mon, 15 Apr 2024 19:13:22 +0200 Subject: tree-wide: use cartesianProduct --- lib/tests/misc.nix | 12 ++++++------ nixos/tests/predictable-interface-names.nix | 2 +- .../development/ocaml-modules/ocaml-freestanding/default.nix | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index accceb4ddf9c..b66f335c74f5 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -33,7 +33,7 @@ let boolToString callPackagesWith callPackageWith - cartesianProductOfSets + cartesianProduct cli composeExtensions composeManyExtensions @@ -1686,17 +1686,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 +1704,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 ]; diff --git a/nixos/tests/predictable-interface-names.nix b/nixos/tests/predictable-interface-names.nix index 51d5e8ae59b9..9ac4f8211e6b 100644 --- a/nixos/tests/predictable-interface-names.nix +++ b/nixos/tests/predictable-interface-names.nix @@ -5,7 +5,7 @@ let inherit (import ../lib/testing-python.nix { inherit system pkgs; }) makeTest; - testCombinations = pkgs.lib.cartesianProductOfSets { + testCombinations = pkgs.lib.cartesianProduct { predictable = [true false]; withNetworkd = [true false]; systemdStage1 = [true false]; diff --git a/pkgs/development/ocaml-modules/ocaml-freestanding/default.nix b/pkgs/development/ocaml-modules/ocaml-freestanding/default.nix index 85b741dbc199..e3627431d959 100644 --- a/pkgs/development/ocaml-modules/ocaml-freestanding/default.nix +++ b/pkgs/development/ocaml-modules/ocaml-freestanding/default.nix @@ -70,7 +70,7 @@ stdenv.mkDerivation rec { maintainers = [ maintainers.sternenseemann ]; homepage = "https://github.com/mirage/ocaml-freestanding"; platforms = builtins.map ({ arch, os }: "${arch}-${os}") - (cartesianProductOfSets { + (cartesianProduct { arch = [ "aarch64" "x86_64" ]; os = [ "linux" ]; } ++ [ -- cgit 1.4.1 From fe2bead78b1034052eca1d695118997f31826924 Mon Sep 17 00:00:00 2001 From: Gabriel Volpe Date: Mon, 15 Apr 2024 19:16:15 +0200 Subject: lib/attrsets: introduce mapCartesianProduct --- lib/attrsets.nix | 34 ++++++++++++++++++++++++++++++++++ lib/default.nix | 2 +- lib/tests/misc.nix | 25 +++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/attrsets.nix b/lib/attrsets.nix index 5c4f735b63da..83f8d0f34186 100644 --- a/lib/attrsets.nix +++ b/lib/attrsets.nix @@ -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`. diff --git a/lib/default.nix b/lib/default.nix index 97a81d4763bf..44a2a5216ec7 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -87,7 +87,7 @@ let recursiveUpdate matchAttrs mergeAttrsList overrideExisting showAttrPath getOutput getBin getLib getDev getMan chooseDevOutputs zipWithNames zip recurseIntoAttrs dontRecurseIntoAttrs cartesianProduct cartesianProductOfSets - updateManyAttrsByPath; + 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/tests/misc.nix b/lib/tests/misc.nix index b66f335c74f5..e15e110682fb 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -71,6 +71,7 @@ let makeIncludePath makeOverridable mapAttrs + mapCartesianProduct matchAttrs mergeAttrs 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 testShowAttrPathExample = { expr = showAttrPath [ "foo" "10" "bar" ]; -- cgit 1.4.1 From d864c36d57b46d2e5215ee67b885dd8c4fe8b764 Mon Sep 17 00:00:00 2001 From: Gabriel Volpe Date: Mon, 15 Apr 2024 19:17:53 +0200 Subject: tree-wide: use mapCartesianProduct --- lib/lists.nix | 22 +++++++++++++++++++--- .../services/x11/display-managers/default.nix | 4 ++-- pkgs/by-name/so/solo5/package.nix | 15 +++++++-------- pkgs/data/fonts/junicode/tests.nix | 7 +++---- pkgs/data/icons/catppuccin-cursors/default.nix | 3 +-- pkgs/data/icons/comixcursors/default.nix | 3 +-- 6 files changed, 33 insertions(+), 21 deletions(-) (limited to 'lib') diff --git a/lib/lists.nix b/lib/lists.nix index c162f921280d..28fa277b22b1 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/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix index 4c62e964c34c..0f9b712c6df5 100644 --- a/nixos/modules/services/x11/display-managers/default.nix +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -284,7 +284,7 @@ in in # We will generate every possible pair of WM and DM. concatLists ( - builtins.map + lib.mapCartesianProduct ({dm, wm}: let sessionName = "${dm.name}${optionalString (wm.name != "none") ("+" + wm.name)}"; script = xsession dm wm; @@ -312,7 +312,7 @@ in providedSessions = [ sessionName ]; }) ) - (cartesianProductOfSets { dm = dms; wm = wms; }) + { dm = dms; wm = wms; } ); }; diff --git a/pkgs/by-name/so/solo5/package.nix b/pkgs/by-name/so/solo5/package.nix index 240c69a40a0f..57ccd1e24b2b 100644 --- a/pkgs/by-name/so/solo5/package.nix +++ b/pkgs/by-name/so/solo5/package.nix @@ -63,16 +63,15 @@ in stdenv.mkDerivation { runHook postCheck ''; - meta = { + meta = with lib; { description = "Sandboxed execution environment"; homepage = "https://github.com/solo5/solo5"; - license = lib.licenses.isc; - maintainers = with lib.maintainers; [ ehmry ]; - platforms = builtins.map ({arch, os}: "${arch}-${os}") - (lib.cartesianProductOfSets { - arch = [ "aarch64" "x86_64" ]; - os = [ "freebsd" "genode" "linux" "openbsd" ]; - }); + license = licenses.isc; + maintainers = [ maintainers.ehmry ]; + platforms = mapCartesianProduct ({ arch, os }: "${arch}-${os}") { + arch = [ "aarch64" "x86_64" ]; + os = [ "freebsd" "genode" "linux" "openbsd" ]; + }; }; } diff --git a/pkgs/data/fonts/junicode/tests.nix b/pkgs/data/fonts/junicode/tests.nix index fda7de31670e..831e60796d12 100644 --- a/pkgs/data/fonts/junicode/tests.nix +++ b/pkgs/data/fonts/junicode/tests.nix @@ -15,14 +15,13 @@ let ''); in builtins.listToAttrs ( - map - texTest - (lib.attrsets.cartesianProductOfSets { + lib.mapCartesianProduct texTest + { tex = [ "xelatex" "lualatex" ]; fonttype = [ "ttf" "otf" ]; package = [ "junicode" ]; file = [ ./test.tex ]; - }) + } ++ [ (texTest { diff --git a/pkgs/data/icons/catppuccin-cursors/default.nix b/pkgs/data/icons/catppuccin-cursors/default.nix index 20e4718515e6..eeb9dd3227f0 100644 --- a/pkgs/data/icons/catppuccin-cursors/default.nix +++ b/pkgs/data/icons/catppuccin-cursors/default.nix @@ -9,9 +9,8 @@ let palette = [ "Frappe" "Latte" "Macchiato" "Mocha" ]; color = [ "Blue" "Dark" "Flamingo" "Green" "Lavender" "Light" "Maroon" "Mauve" "Peach" "Pink" "Red" "Rosewater" "Sapphire" "Sky" "Teal" "Yellow" ]; }; - product = lib.attrsets.cartesianProductOfSets dimensions; variantName = { palette, color }: (lib.strings.toLower palette) + color; - variants = map variantName product; + variants = lib.mapCartesianProduct variantName dimensions; in stdenvNoCC.mkDerivation rec { pname = "catppuccin-cursors"; diff --git a/pkgs/data/icons/comixcursors/default.nix b/pkgs/data/icons/comixcursors/default.nix index 1c4fdc195180..735ff686b49c 100644 --- a/pkgs/data/icons/comixcursors/default.nix +++ b/pkgs/data/icons/comixcursors/default.nix @@ -7,14 +7,13 @@ let thickness = [ "" "Slim_" ]; # Thick or slim edges. handedness = [ "" "LH_" ]; # Right- or left-handed. }; - product = lib.cartesianProductOfSets dimensions; variantName = { color, opacity, thickness, handedness }: "${handedness}${opacity}${thickness}${color}"; variants = # (The order of this list is already good looking enough to show in the # meta.longDescription.) - map variantName product; + lib.mapCartesianProduct variantName dimensions; in stdenvNoCC.mkDerivation rec { pname = "comixcursors"; -- cgit 1.4.1 From 7b687a59cd8ee5db7cfd8067943149dd0d9215cf Mon Sep 17 00:00:00 2001 From: Gabriel Volpe Date: Mon, 15 Apr 2024 19:18:41 +0200 Subject: lib/tests: apply lints --- lib/tests/misc.nix | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'lib') diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index e15e110682fb..cf4a185c1468 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -75,7 +75,6 @@ let matchAttrs mergeAttrs meta - mkOption mod nameValuePair optionalDrvAttr @@ -118,7 +117,6 @@ let expr = (builtins.tryEval expr).success; expected = true; }; - testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr); testSanitizeDerivationName = { name, expected }: let @@ -1416,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"; @@ -1430,7 +1428,7 @@ runTests { there test''; }; - expected = rec { + expected = { list = '' [ 3 @@ -1468,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; -- cgit 1.4.1