2 Operations on attribute sets.
7 inherit (builtins) head length;
8 inherit (lib.trivial) oldestSupportedReleaseIsAtLeast mergeAttrs warn warnIf;
9 inherit (lib.strings) concatStringsSep concatMapStringsSep escapeNixIdentifier sanitizeDerivationName;
10 inherit (lib.lists) filter foldr foldl' concatMap elemAt all partition groupBy take foldl;
14 inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs intersectAttrs;
18 Return an attribute from nested attribute sets.
20 Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
23 (x.a.b or 6) == attrByPath ["a" "b"] 6 x
25 (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
33 : A list of strings representing the attribute path to return from `set`
37 : Default value if `attrPath` does not resolve to an existing value
41 : The nested attribute set to select values from
46 attrByPath :: [String] -> Any -> AttrSet -> Any
51 ## `lib.attrsets.attrByPath` usage example
54 x = { a = { b = 3; }; }
55 # ["a" "b"] is equivalent to x.a.b
56 # 6 is a default value to return if the path does not exist in attrset
57 attrByPath ["a" "b"] 6 x
59 attrByPath ["z" "z"] 6 x
70 lenAttrPath = length attrPath;
72 if n == lenAttrPath then s
75 attr = elemAt attrPath n;
77 if s ? ${attr} then attrByPath' (n + 1) s.${attr}
85 Return if an attribute from nested attribute set exists.
87 Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
90 (x?a.b) == hasAttrByPath ["a" "b"] x
92 (x?${f p}."example.com") == hasAttrByPath [ (f p) "example.com" ] x
97 hasAttrByPath [] x == true
105 : A list of strings representing the attribute path to check from `set`
109 : The nested attribute set to check
114 hasAttrByPath :: [String] -> AttrSet -> Bool
119 ## `lib.attrsets.hasAttrByPath` usage example
122 x = { a = { b = 3; }; }
123 hasAttrByPath ["a" "b"] x
125 hasAttrByPath ["z" "z"] x
127 hasAttrByPath [] (throw "no need")
137 lenAttrPath = length attrPath;
138 hasAttrByPath' = n: s: (
139 n == lenAttrPath || (
141 attr = elemAt attrPath n;
143 if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr}
151 Return the longest prefix of an attribute path that refers to an existing attribute in a nesting of attribute sets.
153 Can be used after [`mapAttrsRecursiveCond`](#function-library-lib.attrsets.mapAttrsRecursiveCond) to apply a condition,
154 although this will evaluate the predicate function on sibling attributes as well.
156 Note that the empty attribute path is valid for all values, so this function only throws an exception if any of its inputs does.
160 attrsets.longestValidPathPrefix [] x == []
164 hasAttrByPath (attrsets.longestValidPathPrefix p x) x == true
172 : A list of strings representing the longest possible path that may be returned.
176 : The nested attribute set to check.
181 attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
186 ## `lib.attrsets.longestValidPathPrefix` usage example
189 x = { a = { b = 3; }; }
190 attrsets.longestValidPathPrefix ["a" "b" "c"] x
192 attrsets.longestValidPathPrefix ["a"] x
194 attrsets.longestValidPathPrefix ["z" "z"] x
196 attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
202 longestValidPathPrefix =
206 lenAttrPath = length attrPath;
207 getPrefixForSetAtIndex =
208 # The nested attribute set to check, if it is an attribute set, which
211 # The index of the attribute we're about to check, as well as
212 # the length of the prefix we've already checked.
215 if remainingPathIndex == lenAttrPath then
216 # All previously checked attributes exist, and no attr names left,
217 # so we return the whole path.
221 attr = elemAt attrPath remainingPathIndex;
223 if remainingSet ? ${attr} then
224 getPrefixForSetAtIndex
225 remainingSet.${attr} # advance from the set to the attribute value
226 (remainingPathIndex + 1) # advance the path
228 # The attribute doesn't exist, so we return the prefix up to the
229 # previously checked length.
230 take remainingPathIndex attrPath;
232 getPrefixForSetAtIndex v 0;
235 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
242 : A list of strings representing the attribute path to set
246 : The value to set at the location described by `attrPath`
251 setAttrByPath :: [String] -> Any -> AttrSet
256 ## `lib.attrsets.setAttrByPath` usage example
259 setAttrByPath ["a" "b"] 3
260 => { a = { b = 3; }; }
269 len = length attrPath;
273 else { ${elemAt attrPath n} = atDepth (n + 1); };
277 Like `attrByPath`, but without a default value. If it doesn't find the
278 path it will throw an error.
280 Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
283 x.a.b == getAttrByPath ["a" "b"] x
285 x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
293 : A list of strings representing the attribute path to get from `set`
297 : The nested attribute set to find the value in.
302 getAttrFromPath :: [String] -> AttrSet -> Any
307 ## `lib.attrsets.getAttrFromPath` usage example
310 x = { a = { b = 3; }; }
311 getAttrFromPath ["a" "b"] x
313 getAttrFromPath ["z" "z"] x
314 => error: cannot find attribute `z.z'
322 attrByPath attrPath (abort ("cannot find attribute `" + concatStringsSep "." attrPath + "'")) set;
325 Map each attribute in the given set and merge them into a new attribute set.
332 : 1\. Function argument
336 : 2\. Function argument
341 concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
346 ## `lib.attrsets.concatMapAttrs` usage example
352 ${name + value} = value;
354 { x = "a"; y = "b"; }
355 => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
360 concatMapAttrs = f: v:
361 foldl' mergeAttrs { }
368 Update or set specific paths of an attribute set.
370 Takes a list of updates to apply and an attribute set to apply them to,
371 and returns the attribute set with the updates applied. Updates are
372 represented as `{ path = ...; update = ...; }` values, where `path` is a
373 list of strings representing the attribute path that should be updated,
374 and `update` is a function that takes the old value at that attribute path
375 as an argument and returns the new
380 - Updates to deeper attribute paths are applied before updates to more
381 shallow attribute paths
383 - Multiple updates to the same attribute path are applied in the order
384 they appear in the update list
386 - If any but the last `path` element leads into a value that is not an
387 attribute set, an error is thrown
389 - If there is an update for an attribute path that doesn't exist,
390 accessing the argument in the update function causes an error, but
391 intermediate attribute sets are implicitly created as needed
396 updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
401 ## `lib.attrsets.updateManyAttrsByPath` usage example
404 updateManyAttrsByPath [
407 update = old: { d = old.c; };
410 path = [ "a" "b" "c" ];
411 update = old: old + 1;
418 => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
423 updateManyAttrsByPath = let
424 # When recursing into attributes, instead of updating the `path` of each
425 # update using `tail`, which needs to allocate an entirely new list,
426 # we just pass a prefix length to use and make sure to only look at the
427 # path without the prefix length, so that we can reuse the original list
429 go = prefixLength: hasValue: value: updates:
431 # Splits updates into ones on this level (split.right)
432 # And ones on levels further down (split.wrong)
433 split = partition (el: length el.path == prefixLength) updates;
435 # Groups updates on further down levels into the attributes they modify
436 nested = groupBy (el: elemAt el.path prefixLength) split.wrong;
438 # Applies only nested modification to the input value
440 # Return the value directly if we don't have any nested modifications
441 if split.wrong == [] then
442 if hasValue then value
444 # Throw an error if there is no value. This `head` call here is
445 # safe, but only in this branch since `go` could only be called
446 # with `hasValue == false` for nested updates, in which case
447 # it's also always called with at least one update
448 let updatePath = (head split.right).path; in
450 ( "updateManyAttrsByPath: Path '${showAttrPath updatePath}' does "
451 + "not exist in the given value, but the first update to this "
452 + "path tries to access the existing value.")
454 # If there are nested modifications, try to apply them to the value
456 # But if we don't have a value, just use an empty attribute set
457 # as the value, but simplify the code a bit
458 mapAttrs (name: go (prefixLength + 1) false null) nested
459 else if isAttrs value then
460 # If we do have a value and it's an attribute set, override it
461 # with the nested modifications
463 mapAttrs (name: go (prefixLength + 1) (value ? ${name}) value.${name}) nested
465 # However if it's not an attribute set, we can't apply the nested
466 # modifications, throw an error
467 let updatePath = (head split.wrong).path; in
469 ( "updateManyAttrsByPath: Path '${showAttrPath updatePath}' needs to "
470 + "be updated, but path '${showAttrPath (take prefixLength updatePath)}' "
471 + "of the given value is not an attribute set, so we can't "
472 + "update an attribute inside of it.");
474 # We get the final result by applying all the updates on this level
475 # after having applied all the nested updates
476 # We use foldl instead of foldl' so that in case of multiple updates,
477 # intermediate values aren't evaluated if not needed
478 in foldl (acc: el: el.update acc) withNestedMods split.right;
480 in updates: value: go 0 true value updates;
483 Return the specified attributes from a set.
490 : The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
494 : The set to get attribute values from
499 attrVals :: [String] -> AttrSet -> [Any]
504 ## `lib.attrsets.attrVals` usage example
507 attrVals ["a" "b" "c"] as
515 set: map (x: set.${x}) nameList;
519 Return the values of all attributes in the given set, sorted by
525 attrValues :: AttrSet -> [Any]
530 ## `lib.attrsets.attrValues` usage example
533 attrValues {c = 3; a = 1; b = 2;}
539 attrValues = builtins.attrValues;
543 Given a set of attribute names, return the set of the corresponding
544 attributes from the given set.
551 : A list of attribute names to get out of `set`
555 : The set to get the named attributes from
560 getAttrs :: [String] -> AttrSet -> AttrSet
565 ## `lib.attrsets.getAttrs` usage example
568 getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
576 attrs: genAttrs names (name: attrs.${name});
579 Collect each attribute named `attr` from a list of attribute
580 sets. Sets that don't contain the named attribute are ignored.
586 : The attribute name to get out of the sets.
590 : The list of attribute sets to go through
595 catAttrs :: String -> [AttrSet] -> [Any]
600 ## `lib.attrsets.catAttrs` usage example
603 catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
609 catAttrs = builtins.catAttrs;
613 Filter an attribute set by removing all attributes for which the
614 given predicate return false.
621 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
625 : The attribute set to filter
630 filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
635 ## `lib.attrsets.filterAttrs` usage example
638 filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
647 removeAttrs set (filter (name: ! pred name set.${name}) (attrNames set));
650 Filter an attribute set recursively by removing all attributes for
651 which the given predicate return false.
658 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
662 : The attribute set to filter
667 filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
672 ## `lib.attrsets.filterAttrsRecursive` usage example
675 filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
681 filterAttrsRecursive =
686 let v = set.${name}; in
687 if pred name v then [
688 (nameValuePair name (
689 if isAttrs v then filterAttrsRecursive pred v
697 Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets.
698 Iterates over every name-value pair in the given attribute set.
699 The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`.
703 There is a completely different function `lib.foldAttrs`
704 which has nothing to do with this function, despite the similar name.
711 : 1\. Function argument
715 : 2\. Function argument
719 : 3\. Function argument
724 foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
729 ## `lib.attrsets.foldlAttrs` usage example
734 sum = acc.sum + value;
735 names = acc.names ++ [name];
737 { sum = 0; names = []; }
745 names = ["bar" "foo"];
749 (throw "function not needed")
758 { z = throw "value not needed"; a = throw "value not needed"; };
762 The accumulator doesn't have to be an attrset.
763 It can be as simple as a number or string.
766 (acc: _: v: acc * 10 + v)
775 foldlAttrs = f: init: set:
777 (acc: name: f acc name set.${name})
782 Apply fold functions to values grouped by key.
789 : A function, given a value and a collector combines the two.
793 : The starting value.
797 : A list of attribute sets to fold together by key.
802 foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
807 ## `lib.attrsets.foldAttrs` usage example
810 foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
822 o // { ${name} = op n.${name} (a.${name} or nul); }
828 Recursively collect sets that verify a given predicate named `pred`
829 from the set `attrs`. The recursion is stopped when the predicate is
837 : Given an attribute's value, determine if recursion should stop.
841 : The attribute set to recursively collect.
846 collect :: (AttrSet -> Bool) -> AttrSet -> [x]
851 ## `lib.attrsets.collect` usage example
854 collect isList { a = { b = ["b"]; }; c = [1]; }
857 collect (x: x ? outPath)
858 { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
859 => [{ outPath = "a/"; } { outPath = "b/"; }]
869 else if isAttrs attrs then
870 concatMap (collect pred) (attrValues attrs)
875 Return the cartesian product of attribute set value combinations.
882 : Attribute set with attributes that are lists of values
887 cartesianProduct :: AttrSet -> [AttrSet]
892 ## `lib.attrsets.cartesianProduct` usage example
895 cartesianProduct { a = [ 1 2 ]; b = [ 10 20 ]; }
908 foldl' (listOfAttrs: attrName:
910 map (listValue: attrs // { ${attrName} = listValue; }) attrsOfLists.${attrName}
912 ) [{}] (attrNames attrsOfLists);
916 Return the result of function f applied to the cartesian product of attribute set value combinations.
917 Equivalent to using cartesianProduct followed by map.
923 : A function, given an attribute set, it returns a new value.
927 : Attribute set with attributes that are lists of values
932 mapCartesianProduct :: (AttrSet -> a) -> AttrSet -> [a]
937 ## `lib.attrsets.mapCartesianProduct` usage example
940 mapCartesianProduct ({a, b}: "${a}-${b}") { a = [ "1" "2" ]; b = [ "3" "4" ]; }
941 => [ "1-3" "1-4" "2-3" "2-4" ]
947 mapCartesianProduct = f: attrsOfLists: map f (cartesianProduct attrsOfLists);
950 Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
966 nameValuePair :: String -> Any -> { name :: String; value :: Any; }
971 ## `lib.attrsets.nameValuePair` usage example
974 nameValuePair "some" 6
975 => { name = "some"; value = 6; }
983 { inherit name value; };
987 Apply a function to each element in an attribute set, creating a new attribute set.
993 : A function that takes an attribute name and its value, and returns the new value for the attribute.
997 : The attribute set to iterate through.
1002 mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
1007 ## `lib.attrsets.mapAttrs` usage example
1010 mapAttrs (name: value: name + "-" + value)
1011 { x = "foo"; y = "bar"; }
1012 => { x = "x-foo"; y = "y-bar"; }
1017 mapAttrs = builtins.mapAttrs;
1021 Like `mapAttrs`, but allows the name of each attribute to be
1022 changed in addition to the value. The applied function should
1023 return both the new name and value as a `nameValuePair`.
1030 : A function, given an attribute's name and value, returns a new `nameValuePair`.
1034 : Attribute set to map over.
1039 mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
1044 ## `lib.attrsets.mapAttrs'` usage example
1047 mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
1048 { x = "a"; y = "b"; }
1049 => { foo_x = "bar-a"; foo_y = "bar-b"; }
1057 listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
1061 Call a function for each attribute in the given set and return
1062 the result in a list.
1068 : A function, given an attribute's name and value, returns a new value.
1072 : Attribute set to map over.
1077 mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
1082 ## `lib.attrsets.mapAttrsToList` usage example
1085 mapAttrsToList (name: value: name + value)
1086 { x = "a"; y = "b"; }
1095 map (name: f name attrs.${name}) (attrNames attrs);
1098 Deconstruct an attrset to a list of name-value pairs as expected by [`builtins.listToAttrs`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-listToAttrs).
1099 Each element of the resulting list is an attribute set with these attributes:
1100 - `name` (string): The name of the attribute
1101 - `value` (any): The value of the attribute
1103 The following is always true:
1105 builtins.listToAttrs (attrsToList attrs) == attrs
1109 The opposite is not always true. In general expect that
1111 attrsToList (builtins.listToAttrs list) != list
1114 This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
1121 : The attribute set to deconstruct.
1126 attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
1131 ## `lib.attrsets.attrsToList` usage example
1134 attrsToList { foo = 1; bar = "asdf"; }
1135 => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
1140 attrsToList = mapAttrsToList nameValuePair;
1144 Like `mapAttrs`, except that it recursively applies itself to the *leaf* attributes of a potentially-nested attribute set:
1145 the second argument of the function will never be an attrset.
1146 Also, the first argument of the mapping function is a *list* of the attribute names that form the path to the leaf attribute.
1148 For a function that gives you control over what counts as a leaf, see `mapAttrsRecursiveCond`.
1150 :::{#map-attrs-recursive-example .example}
1151 # Map over leaf attributes
1154 mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
1155 { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
1159 { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
1165 mapAttrsRecursive :: ([String] -> a -> b) -> AttrSet -> AttrSet
1171 mapAttrsRecursiveCond (as: true) f set;
1175 Like `mapAttrsRecursive`, but it takes an additional predicate that tells it whether to recurse into an attribute set.
1176 If the predicate returns false, `mapAttrsRecursiveCond` does not recurse, but instead applies the mapping function.
1177 If the predicate returns true, it does recurse, and does not apply the mapping function.
1179 :::{#map-attrs-recursive-cond-example .example}
1180 # Map over an leaf attributes defined by a condition
1182 Map derivations to their `name` attribute.
1183 Derivatons are identified as attribute sets that contain `{ type = "derivation"; }`.
1185 mapAttrsRecursiveCond
1186 (as: !(as ? "type" && as.type == "derivation"))
1194 mapAttrsRecursiveCond :: (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
1197 mapAttrsRecursiveCond =
1205 if isAttrs value && cond value
1206 then recurse (path ++ [ name ]) value
1207 else f (path ++ [ name ]) value);
1213 Generate an attribute set by mapping a function over a list of
1221 : Names of values in the resulting attribute set.
1225 : A function, given the name of the attribute, returns the attribute's value.
1230 genAttrs :: [ String ] -> (String -> Any) -> AttrSet
1235 ## `lib.attrsets.genAttrs` usage example
1238 genAttrs [ "foo" "bar" ] (name: "x_" + name)
1239 => { foo = "x_foo"; bar = "x_bar"; }
1247 listToAttrs (map (n: nameValuePair n (f n)) names);
1251 Check whether the argument is a derivation. Any set with
1252 `{ type = "derivation"; }` counts as a derivation.
1264 isDerivation :: Any -> Bool
1269 ## `lib.attrsets.isDerivation` usage example
1272 nixpkgs = import <nixpkgs> {}
1273 isDerivation nixpkgs.ruby
1275 isDerivation "foobar"
1282 value: value.type or null == "derivation";
1285 Converts a store path to a fake derivation.
1292 : A store path to convert to a derivation.
1297 toDerivation :: Path -> Derivation
1303 path' = builtins.storePath path;
1305 { type = "derivation";
1306 name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path'));
1308 outputs = [ "out" ];
1316 If `cond` is true, return the attribute set `as`,
1317 otherwise an empty attribute set.
1324 : Condition under which the `as` attribute set is returned.
1328 : The attribute set to return if `cond` is `true`.
1333 optionalAttrs :: Bool -> AttrSet -> AttrSet
1338 ## `lib.attrsets.optionalAttrs` usage example
1341 optionalAttrs (true) { my = "set"; }
1343 optionalAttrs (false) { my = "set"; }
1352 if cond then as else {};
1356 Merge sets of attributes and use the function `f` to merge attributes
1364 : List of attribute names to zip.
1368 : A function, accepts an attribute name, all the values, and returns a combined value.
1372 : List of values from the list of attribute sets.
1377 zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1382 ## `lib.attrsets.zipAttrsWithNames` usage example
1385 zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
1386 => { a = ["x" "y"]; }
1395 listToAttrs (map (name: {
1397 value = f name (catAttrs name sets);
1402 Merge sets of attributes and use the function f to merge attribute values.
1403 Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
1405 Implementation note: Common names appear multiple times in the list of
1406 names, hopefully this does not affect the system because the maximal
1407 laziness avoid computing twice the same expression and `listToAttrs` does
1408 not care about duplicated attribute names.
1413 zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1418 ## `lib.attrsets.zipAttrsWith` usage example
1421 zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
1422 => { a = ["x" "y"]; b = ["z"]; }
1428 builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
1432 Merge sets of attributes and combine each attribute value in to a list.
1434 Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
1439 zipAttrs :: [ AttrSet ] -> AttrSet
1444 ## `lib.attrsets.zipAttrs` usage example
1447 zipAttrs [{a = "x";} {a = "y"; b = "z";}]
1448 => { a = ["x" "y"]; b = ["z"]; }
1453 zipAttrs = zipAttrsWith (name: values: values);
1456 Merge a list of attribute sets together using the `//` operator.
1457 In case of duplicate attributes, values from later list elements take precedence over earlier ones.
1458 The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
1459 For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
1466 : 1\. Function argument
1471 mergeAttrsList :: [ Attrs ] -> Attrs
1476 ## `lib.attrsets.mergeAttrsList` usage example
1479 mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
1480 => { a = 0; b = 1; c = 2; d = 3; }
1481 mergeAttrsList [ { a = 0; } { a = 1; } ]
1487 mergeAttrsList = list:
1489 # `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
1490 # Type: Int -> Int -> Attrs
1491 binaryMerge = start: end:
1492 # assert start < end; # Invariant
1493 if end - start >= 2 then
1494 # If there's at least 2 elements, split the range in two, recurse on each part and merge the result
1495 # The invariant is satisfied because each half will have at least 1 element
1496 binaryMerge start (start + (end - start) / 2)
1497 // binaryMerge (start + (end - start) / 2) end
1499 # Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
1503 # Calling binaryMerge as below would not satisfy its invariant
1506 binaryMerge 0 (length list);
1510 Does the same as the update operator '//' except that attributes are
1511 merged until the given predicate is verified. The predicate should
1512 accept 3 arguments which are the path to reach the attribute, a part of
1513 the first attribute set and a part of the second attribute set. When
1514 the predicate is satisfied, the value of the first attribute set is
1515 replaced by the value of the second attribute set.
1522 : Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
1526 : Left attribute set of the merge.
1530 : Right attribute set of the merge.
1535 recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
1540 ## `lib.attrsets.recursiveUpdateUntil` usage example
1543 recursiveUpdateUntil (path: l: r: path == ["foo"]) {
1544 # first attribute set
1549 #second attribute set
1556 foo.bar = 1; # 'foo.*' from the second set
1558 bar = 3; # 'bar' from the first set
1559 baz = 4; # 'baz' from the second set
1565 recursiveUpdateUntil =
1570 zipAttrsWith (n: values:
1571 let here = attrPath ++ [n]; in
1572 if length values == 1
1573 || pred here (elemAt values 1) (head values) then
1582 A recursive variant of the update operator ‘//’. The recursion
1583 stops when one of the attribute values is not an attribute set,
1584 in which case the right hand side value takes precedence over the
1585 left hand side value.
1592 : Left attribute set of the merge.
1596 : Right attribute set of the merge.
1601 recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
1606 ## `lib.attrsets.recursiveUpdate` usage example
1610 boot.loader.grub.enable = true;
1611 boot.loader.grub.device = "/dev/hda";
1613 boot.loader.grub.device = "";
1617 boot.loader.grub.enable = true;
1618 boot.loader.grub.device = "";
1627 recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
1631 Recurse into every attribute set of the first argument and check that:
1632 - Each attribute path also exists in the second argument.
1633 - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
1640 : Attribute set structure to match
1644 : Attribute set to check
1649 matchAttrs :: AttrSet -> AttrSet -> Bool
1654 ## `lib.attrsets.matchAttrs` usage example
1657 matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
1666 assert isAttrs pattern;
1668 ( # Compare equality between `pattern` & `attrs`.
1670 # Missing attr, not equal.
1671 attrs ? ${attr} && (
1673 lhs = pattern.${attr};
1674 rhs = attrs.${attr};
1676 # If attrset check recursively
1677 if isAttrs lhs then isAttrs rhs && matchAttrs lhs rhs
1681 (attrNames pattern);
1684 Override only the attributes that are already present in the old set
1685 useful for deep-overriding.
1692 : Original attribute set
1696 : Attribute set with attributes to override in `old`.
1701 overrideExisting :: AttrSet -> AttrSet -> AttrSet
1706 ## `lib.attrsets.overrideExisting` usage example
1709 overrideExisting {} { a = 1; }
1711 overrideExisting { b = 2; } { a = 1; }
1713 overrideExisting { a = 3; b = 2; } { a = 1; }
1714 => { a = 1; b = 2; }
1722 mapAttrs (name: value: new.${name} or value) old;
1726 Turns a list of strings into a human-readable description of those
1727 strings represented as an attribute path. The result of this function is
1728 not intended to be machine-readable.
1729 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
1736 : Attribute path to render to a string
1741 showAttrPath :: [String] -> String
1746 ## `lib.attrsets.showAttrPath` usage example
1749 showAttrPath [ "foo" "10" "bar" ]
1752 => "<root attribute path>"
1759 if path == [] then "<root attribute path>"
1760 else concatMapStringsSep "." escapeNixIdentifier path;
1764 Get a package output.
1765 If no output is found, fallback to `.out` and then to the default.
1766 The function is idempotent: `getOutput "b" (getOutput "a" p) == getOutput "a" p`.
1773 : 1\. Function argument
1777 : 2\. Function argument
1782 getOutput :: String -> :: Derivation -> Derivation
1787 ## `lib.attrsets.getOutput` usage example
1790 "${getOutput "dev" pkgs.openssl}"
1791 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1796 getOutput = output: pkg:
1797 if ! pkg ? outputSpecified || ! pkg.outputSpecified
1798 then pkg.${output} or pkg.out or pkg
1802 Get the first of the `outputs` provided by the package, or the default.
1803 This function is alligned with `_overrideFirst()` from the `multiple-outputs.sh` setup hook.
1804 Like `getOutput`, the function is idempotent.
1810 : 1\. Function argument
1814 : 2\. Function argument
1819 getFirstOutput :: [String] -> Derivation -> Derivation
1824 ## `lib.attrsets.getFirstOutput` usage example
1827 "${getFirstOutput [ "include" "dev" ] pkgs.openssl}"
1828 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r-dev"
1836 outputs = builtins.filter (name: hasAttr name pkg) candidates;
1837 output = builtins.head outputs;
1839 if pkg.outputSpecified or false || outputs == [ ] then
1845 Get a package's `bin` output.
1846 If the output does not exist, fallback to `.out` and then to the default.
1852 : The package whose `bin` output will be retrieved.
1857 getBin :: Derivation -> Derivation
1862 ## `lib.attrsets.getBin` usage example
1865 "${getBin pkgs.openssl}"
1866 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r"
1871 getBin = getOutput "bin";
1875 Get a package's `lib` output.
1876 If the output does not exist, fallback to `.out` and then to the default.
1882 : The package whose `lib` output will be retrieved.
1887 getLib :: Derivation -> Derivation
1892 ## `lib.attrsets.getLib` usage example
1895 "${getLib pkgs.openssl}"
1896 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
1901 getLib = getOutput "lib";
1904 Get a package's `static` output.
1905 If the output does not exist, fallback to `.lib`, then to `.out`, and then to the default.
1911 : The package whose `static` output will be retrieved.
1916 getStatic :: Derivation -> Derivation
1921 ## `lib.attrsets.getStatic` usage example
1924 "${lib.getStatic pkgs.glibc}"
1925 => "/nix/store/00000000000000000000000000000000-glibc-2.39-52-static"
1930 getStatic = getFirstOutput [ "static" "lib" "out" ];
1934 Get a package's `dev` output.
1935 If the output does not exist, fallback to `.out` and then to the default.
1941 : The package whose `dev` output will be retrieved.
1946 getDev :: Derivation -> Derivation
1951 ## `lib.attrsets.getDev` usage example
1954 "${getDev pkgs.openssl}"
1955 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1960 getDev = getOutput "dev";
1963 Get a package's `include` output.
1964 If the output does not exist, fallback to `.dev`, then to `.out`, and then to the default.
1970 : The package whose `include` output will be retrieved.
1975 getInclude :: Derivation -> Derivation
1980 ## `lib.attrsets.getInclude` usage example
1983 "${getInclude pkgs.openssl}"
1984 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r-dev"
1989 getInclude = getFirstOutput [ "include" "dev" "out" ];
1993 Get a package's `man` output.
1994 If the output does not exist, fallback to `.out` and then to the default.
2000 : The package whose `man` output will be retrieved.
2005 getMan :: Derivation -> Derivation
2010 ## `lib.attrsets.getMan` usage example
2013 "${getMan pkgs.openssl}"
2014 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
2019 getMan = getOutput "man";
2022 Pick the outputs of packages to place in `buildInputs`
2033 chooseDevOutputs :: [Derivation] -> [Derivation]
2036 chooseDevOutputs = builtins.map getDev;
2039 Make various Nix tools consider the contents of the resulting
2040 attribute set when looking for what to build, find, etc.
2042 This function only affects a single attribute set; it does not
2043 apply itself recursively for nested attribute sets.
2050 : An attribute set to scan for derivations.
2055 recurseIntoAttrs :: AttrSet -> AttrSet
2060 ## `lib.attrsets.recurseIntoAttrs` usage example
2063 { pkgs ? import <nixpkgs> {} }:
2065 myTools = pkgs.lib.recurseIntoAttrs {
2066 inherit (pkgs) hello figlet;
2075 attrs // { recurseForDerivations = true; };
2078 Undo the effect of recurseIntoAttrs.
2085 : An attribute set to not scan for derivations.
2090 dontRecurseIntoAttrs :: AttrSet -> AttrSet
2093 dontRecurseIntoAttrs =
2095 attrs // { recurseForDerivations = false; };
2098 `unionOfDisjoint x y` is equal to `x // y // z` where the
2099 attrnames in `z` are the intersection of the attrnames in `x` and
2100 `y`, and all values `assert` with an error message. This
2101 operator is commutative, unlike (//).
2108 : 1\. Function argument
2112 : 2\. Function argument
2117 unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
2120 unionOfDisjoint = x: y:
2122 intersection = builtins.intersectAttrs x y;
2123 collisions = lib.concatStringsSep " " (builtins.attrNames intersection);
2124 mask = builtins.mapAttrs (name: value: builtins.throw
2125 "unionOfDisjoint: collision on ${name}; complete list: ${collisions}")
2132 "lib.zipWithNames is a deprecated alias of lib.zipAttrsWithNames." zipAttrsWithNames;
2136 "lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;
2139 cartesianProductOfSets = warnIf (oldestSupportedReleaseIsAtLeast 2405)
2140 "lib.cartesianProductOfSets is a deprecated alias of lib.cartesianProduct." cartesianProduct;