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) 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 listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
651 Filter an attribute set recursively by removing all attributes for
652 which the given predicate return false.
659 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
663 : The attribute set to filter
668 filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
673 ## `lib.attrsets.filterAttrsRecursive` usage example
676 filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
682 filterAttrsRecursive =
687 let v = set.${name}; in
688 if pred name v then [
689 (nameValuePair name (
690 if isAttrs v then filterAttrsRecursive pred v
698 Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets.
699 Iterates over every name-value pair in the given attribute set.
700 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`.
704 There is a completely different function `lib.foldAttrs`
705 which has nothing to do with this function, despite the similar name.
712 : 1\. Function argument
716 : 2\. Function argument
720 : 3\. Function argument
725 foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
730 ## `lib.attrsets.foldlAttrs` usage example
735 sum = acc.sum + value;
736 names = acc.names ++ [name];
738 { sum = 0; names = []; }
746 names = ["bar" "foo"];
750 (throw "function not needed")
759 { z = throw "value not needed"; a = throw "value not needed"; };
763 The accumulator doesn't have to be an attrset.
764 It can be as simple as a number or string.
767 (acc: _: v: acc * 10 + v)
776 foldlAttrs = f: init: set:
778 (acc: name: f acc name set.${name})
783 Apply fold functions to values grouped by key.
790 : A function, given a value and a collector combines the two.
794 : The starting value.
798 : A list of attribute sets to fold together by key.
803 foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
808 ## `lib.attrsets.foldAttrs` usage example
811 foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
823 o // { ${name} = op n.${name} (a.${name} or nul); }
829 Recursively collect sets that verify a given predicate named `pred`
830 from the set `attrs`. The recursion is stopped when the predicate is
838 : Given an attribute's value, determine if recursion should stop.
842 : The attribute set to recursively collect.
847 collect :: (AttrSet -> Bool) -> AttrSet -> [x]
852 ## `lib.attrsets.collect` usage example
855 collect isList { a = { b = ["b"]; }; c = [1]; }
858 collect (x: x ? outPath)
859 { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
860 => [{ outPath = "a/"; } { outPath = "b/"; }]
870 else if isAttrs attrs then
871 concatMap (collect pred) (attrValues attrs)
876 Return the cartesian product of attribute set value combinations.
883 : Attribute set with attributes that are lists of values
888 cartesianProduct :: AttrSet -> [AttrSet]
893 ## `lib.attrsets.cartesianProduct` usage example
896 cartesianProduct { a = [ 1 2 ]; b = [ 10 20 ]; }
909 foldl' (listOfAttrs: attrName:
911 map (listValue: attrs // { ${attrName} = listValue; }) attrsOfLists.${attrName}
913 ) [{}] (attrNames attrsOfLists);
917 Return the result of function f applied to the cartesian product of attribute set value combinations.
918 Equivalent to using cartesianProduct followed by map.
924 : A function, given an attribute set, it returns a new value.
928 : Attribute set with attributes that are lists of values
933 mapCartesianProduct :: (AttrSet -> a) -> AttrSet -> [a]
938 ## `lib.attrsets.mapCartesianProduct` usage example
941 mapCartesianProduct ({a, b}: "${a}-${b}") { a = [ "1" "2" ]; b = [ "3" "4" ]; }
942 => [ "1-3" "1-4" "2-3" "2-4" ]
948 mapCartesianProduct = f: attrsOfLists: map f (cartesianProduct attrsOfLists);
951 Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
967 nameValuePair :: String -> Any -> { name :: String; value :: Any; }
972 ## `lib.attrsets.nameValuePair` usage example
975 nameValuePair "some" 6
976 => { name = "some"; value = 6; }
984 { inherit name value; };
988 Apply a function to each element in an attribute set, creating a new attribute set.
994 : A function that takes an attribute name and its value, and returns the new value for the attribute.
998 : The attribute set to iterate through.
1003 mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
1008 ## `lib.attrsets.mapAttrs` usage example
1011 mapAttrs (name: value: name + "-" + value)
1012 { x = "foo"; y = "bar"; }
1013 => { x = "x-foo"; y = "y-bar"; }
1018 mapAttrs = builtins.mapAttrs;
1022 Like `mapAttrs`, but allows the name of each attribute to be
1023 changed in addition to the value. The applied function should
1024 return both the new name and value as a `nameValuePair`.
1031 : A function, given an attribute's name and value, returns a new `nameValuePair`.
1035 : Attribute set to map over.
1040 mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
1045 ## `lib.attrsets.mapAttrs'` usage example
1048 mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
1049 { x = "a"; y = "b"; }
1050 => { foo_x = "bar-a"; foo_y = "bar-b"; }
1058 listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
1062 Call a function for each attribute in the given set and return
1063 the result in a list.
1069 : A function, given an attribute's name and value, returns a new value.
1073 : Attribute set to map over.
1078 mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
1083 ## `lib.attrsets.mapAttrsToList` usage example
1086 mapAttrsToList (name: value: name + value)
1087 { x = "a"; y = "b"; }
1096 map (name: f name attrs.${name}) (attrNames attrs);
1099 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).
1100 Each element of the resulting list is an attribute set with these attributes:
1101 - `name` (string): The name of the attribute
1102 - `value` (any): The value of the attribute
1104 The following is always true:
1106 builtins.listToAttrs (attrsToList attrs) == attrs
1110 The opposite is not always true. In general expect that
1112 attrsToList (builtins.listToAttrs list) != list
1115 This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
1122 : The attribute set to deconstruct.
1127 attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
1132 ## `lib.attrsets.attrsToList` usage example
1135 attrsToList { foo = 1; bar = "asdf"; }
1136 => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
1141 attrsToList = mapAttrsToList nameValuePair;
1145 Like `mapAttrs`, except that it recursively applies itself to the *leaf* attributes of a potentially-nested attribute set:
1146 the second argument of the function will never be an attrset.
1147 Also, the first argument of the mapping function is a *list* of the attribute names that form the path to the leaf attribute.
1149 For a function that gives you control over what counts as a leaf, see `mapAttrsRecursiveCond`.
1151 :::{#map-attrs-recursive-example .example}
1152 # Map over leaf attributes
1155 mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
1156 { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
1160 { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
1166 mapAttrsRecursive :: ([String] -> a -> b) -> AttrSet -> AttrSet
1172 mapAttrsRecursiveCond (as: true) f set;
1176 Like `mapAttrsRecursive`, but it takes an additional predicate that tells it whether to recurse into an attribute set.
1177 If the predicate returns false, `mapAttrsRecursiveCond` does not recurse, but instead applies the mapping function.
1178 If the predicate returns true, it does recurse, and does not apply the mapping function.
1180 :::{#map-attrs-recursive-cond-example .example}
1181 # Map over an leaf attributes defined by a condition
1183 Map derivations to their `name` attribute.
1184 Derivatons are identified as attribute sets that contain `{ type = "derivation"; }`.
1186 mapAttrsRecursiveCond
1187 (as: !(as ? "type" && as.type == "derivation"))
1195 mapAttrsRecursiveCond :: (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
1198 mapAttrsRecursiveCond =
1206 if isAttrs value && cond value
1207 then recurse (path ++ [ name ]) value
1208 else f (path ++ [ name ]) value);
1214 Generate an attribute set by mapping a function over a list of
1222 : Names of values in the resulting attribute set.
1226 : A function, given the name of the attribute, returns the attribute's value.
1231 genAttrs :: [ String ] -> (String -> Any) -> AttrSet
1236 ## `lib.attrsets.genAttrs` usage example
1239 genAttrs [ "foo" "bar" ] (name: "x_" + name)
1240 => { foo = "x_foo"; bar = "x_bar"; }
1248 listToAttrs (map (n: nameValuePair n (f n)) names);
1252 Check whether the argument is a derivation. Any set with
1253 `{ type = "derivation"; }` counts as a derivation.
1265 isDerivation :: Any -> Bool
1270 ## `lib.attrsets.isDerivation` usage example
1273 nixpkgs = import <nixpkgs> {}
1274 isDerivation nixpkgs.ruby
1276 isDerivation "foobar"
1283 value: value.type or null == "derivation";
1286 Converts a store path to a fake derivation.
1293 : A store path to convert to a derivation.
1298 toDerivation :: Path -> Derivation
1304 path' = builtins.storePath path;
1306 { type = "derivation";
1307 name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path'));
1309 outputs = [ "out" ];
1317 If `cond` is true, return the attribute set `as`,
1318 otherwise an empty attribute set.
1325 : Condition under which the `as` attribute set is returned.
1329 : The attribute set to return if `cond` is `true`.
1334 optionalAttrs :: Bool -> AttrSet -> AttrSet
1339 ## `lib.attrsets.optionalAttrs` usage example
1342 optionalAttrs (true) { my = "set"; }
1344 optionalAttrs (false) { my = "set"; }
1353 if cond then as else {};
1357 Merge sets of attributes and use the function `f` to merge attributes
1365 : List of attribute names to zip.
1369 : A function, accepts an attribute name, all the values, and returns a combined value.
1373 : List of values from the list of attribute sets.
1378 zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1383 ## `lib.attrsets.zipAttrsWithNames` usage example
1386 zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
1387 => { a = ["x" "y"]; }
1396 listToAttrs (map (name: {
1398 value = f name (catAttrs name sets);
1403 Merge sets of attributes and use the function f to merge attribute values.
1404 Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
1406 Implementation note: Common names appear multiple times in the list of
1407 names, hopefully this does not affect the system because the maximal
1408 laziness avoid computing twice the same expression and `listToAttrs` does
1409 not care about duplicated attribute names.
1414 zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1419 ## `lib.attrsets.zipAttrsWith` usage example
1422 zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
1423 => { a = ["x" "y"]; b = ["z"]; }
1429 builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
1433 Merge sets of attributes and combine each attribute value in to a list.
1435 Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
1440 zipAttrs :: [ AttrSet ] -> AttrSet
1445 ## `lib.attrsets.zipAttrs` usage example
1448 zipAttrs [{a = "x";} {a = "y"; b = "z";}]
1449 => { a = ["x" "y"]; b = ["z"]; }
1454 zipAttrs = zipAttrsWith (name: values: values);
1457 Merge a list of attribute sets together using the `//` operator.
1458 In case of duplicate attributes, values from later list elements take precedence over earlier ones.
1459 The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
1460 For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
1467 : 1\. Function argument
1472 mergeAttrsList :: [ Attrs ] -> Attrs
1477 ## `lib.attrsets.mergeAttrsList` usage example
1480 mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
1481 => { a = 0; b = 1; c = 2; d = 3; }
1482 mergeAttrsList [ { a = 0; } { a = 1; } ]
1488 mergeAttrsList = list:
1490 # `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
1491 # Type: Int -> Int -> Attrs
1492 binaryMerge = start: end:
1493 # assert start < end; # Invariant
1494 if end - start >= 2 then
1495 # If there's at least 2 elements, split the range in two, recurse on each part and merge the result
1496 # The invariant is satisfied because each half will have at least 1 element
1497 binaryMerge start (start + (end - start) / 2)
1498 // binaryMerge (start + (end - start) / 2) end
1500 # Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
1504 # Calling binaryMerge as below would not satisfy its invariant
1507 binaryMerge 0 (length list);
1511 Does the same as the update operator '//' except that attributes are
1512 merged until the given predicate is verified. The predicate should
1513 accept 3 arguments which are the path to reach the attribute, a part of
1514 the first attribute set and a part of the second attribute set. When
1515 the predicate is satisfied, the value of the first attribute set is
1516 replaced by the value of the second attribute set.
1523 : 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.
1527 : Left attribute set of the merge.
1531 : Right attribute set of the merge.
1536 recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
1541 ## `lib.attrsets.recursiveUpdateUntil` usage example
1544 recursiveUpdateUntil (path: l: r: path == ["foo"]) {
1545 # first attribute set
1550 #second attribute set
1557 foo.bar = 1; # 'foo.*' from the second set
1559 bar = 3; # 'bar' from the first set
1560 baz = 4; # 'baz' from the second set
1566 recursiveUpdateUntil =
1571 zipAttrsWith (n: values:
1572 let here = attrPath ++ [n]; in
1573 if length values == 1
1574 || pred here (elemAt values 1) (head values) then
1583 A recursive variant of the update operator ‘//’. The recursion
1584 stops when one of the attribute values is not an attribute set,
1585 in which case the right hand side value takes precedence over the
1586 left hand side value.
1593 : Left attribute set of the merge.
1597 : Right attribute set of the merge.
1602 recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
1607 ## `lib.attrsets.recursiveUpdate` usage example
1611 boot.loader.grub.enable = true;
1612 boot.loader.grub.device = "/dev/hda";
1614 boot.loader.grub.device = "";
1618 boot.loader.grub.enable = true;
1619 boot.loader.grub.device = "";
1628 recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
1632 Recurse into every attribute set of the first argument and check that:
1633 - Each attribute path also exists in the second argument.
1634 - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
1641 : Attribute set structure to match
1645 : Attribute set to check
1650 matchAttrs :: AttrSet -> AttrSet -> Bool
1655 ## `lib.attrsets.matchAttrs` usage example
1658 matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
1667 assert isAttrs pattern;
1669 ( # Compare equality between `pattern` & `attrs`.
1671 # Missing attr, not equal.
1672 attrs ? ${attr} && (
1674 lhs = pattern.${attr};
1675 rhs = attrs.${attr};
1677 # If attrset check recursively
1678 if isAttrs lhs then isAttrs rhs && matchAttrs lhs rhs
1682 (attrNames pattern);
1685 Override only the attributes that are already present in the old set
1686 useful for deep-overriding.
1693 : Original attribute set
1697 : Attribute set with attributes to override in `old`.
1702 overrideExisting :: AttrSet -> AttrSet -> AttrSet
1707 ## `lib.attrsets.overrideExisting` usage example
1710 overrideExisting {} { a = 1; }
1712 overrideExisting { b = 2; } { a = 1; }
1714 overrideExisting { a = 3; b = 2; } { a = 1; }
1715 => { a = 1; b = 2; }
1723 mapAttrs (name: value: new.${name} or value) old;
1727 Turns a list of strings into a human-readable description of those
1728 strings represented as an attribute path. The result of this function is
1729 not intended to be machine-readable.
1730 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
1737 : Attribute path to render to a string
1742 showAttrPath :: [String] -> String
1747 ## `lib.attrsets.showAttrPath` usage example
1750 showAttrPath [ "foo" "10" "bar" ]
1753 => "<root attribute path>"
1760 if path == [] then "<root attribute path>"
1761 else concatMapStringsSep "." escapeNixIdentifier path;
1765 Get a package output.
1766 If no output is found, fallback to `.out` and then to the default.
1767 The function is idempotent: `getOutput "b" (getOutput "a" p) == getOutput "a" p`.
1774 : 1\. Function argument
1778 : 2\. Function argument
1783 getOutput :: String -> :: Derivation -> Derivation
1788 ## `lib.attrsets.getOutput` usage example
1791 "${getOutput "dev" pkgs.openssl}"
1792 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1797 getOutput = output: pkg:
1798 if ! pkg ? outputSpecified || ! pkg.outputSpecified
1799 then pkg.${output} or pkg.out or pkg
1803 Get the first of the `outputs` provided by the package, or the default.
1804 This function is alligned with `_overrideFirst()` from the `multiple-outputs.sh` setup hook.
1805 Like `getOutput`, the function is idempotent.
1811 : 1\. Function argument
1815 : 2\. Function argument
1820 getFirstOutput :: [String] -> Derivation -> Derivation
1825 ## `lib.attrsets.getFirstOutput` usage example
1828 "${getFirstOutput [ "include" "dev" ] pkgs.openssl}"
1829 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r-dev"
1837 outputs = builtins.filter (name: hasAttr name pkg) candidates;
1838 output = builtins.head outputs;
1840 if pkg.outputSpecified or false || outputs == [ ] then
1846 Get a package's `bin` output.
1847 If the output does not exist, fallback to `.out` and then to the default.
1853 : The package whose `bin` output will be retrieved.
1858 getBin :: Derivation -> Derivation
1863 ## `lib.attrsets.getBin` usage example
1866 "${getBin pkgs.openssl}"
1867 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r"
1872 getBin = getOutput "bin";
1876 Get a package's `lib` output.
1877 If the output does not exist, fallback to `.out` and then to the default.
1883 : The package whose `lib` output will be retrieved.
1888 getLib :: Derivation -> Derivation
1893 ## `lib.attrsets.getLib` usage example
1896 "${getLib pkgs.openssl}"
1897 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
1902 getLib = getOutput "lib";
1905 Get a package's `static` output.
1906 If the output does not exist, fallback to `.lib`, then to `.out`, and then to the default.
1912 : The package whose `static` output will be retrieved.
1917 getStatic :: Derivation -> Derivation
1922 ## `lib.attrsets.getStatic` usage example
1925 "${lib.getStatic pkgs.glibc}"
1926 => "/nix/store/00000000000000000000000000000000-glibc-2.39-52-static"
1931 getStatic = getFirstOutput [ "static" "lib" "out" ];
1935 Get a package's `dev` output.
1936 If the output does not exist, fallback to `.out` and then to the default.
1942 : The package whose `dev` output will be retrieved.
1947 getDev :: Derivation -> Derivation
1952 ## `lib.attrsets.getDev` usage example
1955 "${getDev pkgs.openssl}"
1956 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1961 getDev = getOutput "dev";
1964 Get a package's `include` output.
1965 If the output does not exist, fallback to `.dev`, then to `.out`, and then to the default.
1971 : The package whose `include` output will be retrieved.
1976 getInclude :: Derivation -> Derivation
1981 ## `lib.attrsets.getInclude` usage example
1984 "${getInclude pkgs.openssl}"
1985 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r-dev"
1990 getInclude = getFirstOutput [ "include" "dev" "out" ];
1994 Get a package's `man` output.
1995 If the output does not exist, fallback to `.out` and then to the default.
2001 : The package whose `man` output will be retrieved.
2006 getMan :: Derivation -> Derivation
2011 ## `lib.attrsets.getMan` usage example
2014 "${getMan pkgs.openssl}"
2015 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
2020 getMan = getOutput "man";
2023 Pick the outputs of packages to place in `buildInputs`
2034 chooseDevOutputs :: [Derivation] -> [Derivation]
2037 chooseDevOutputs = builtins.map getDev;
2040 Make various Nix tools consider the contents of the resulting
2041 attribute set when looking for what to build, find, etc.
2043 This function only affects a single attribute set; it does not
2044 apply itself recursively for nested attribute sets.
2051 : An attribute set to scan for derivations.
2056 recurseIntoAttrs :: AttrSet -> AttrSet
2061 ## `lib.attrsets.recurseIntoAttrs` usage example
2064 { pkgs ? import <nixpkgs> {} }:
2066 myTools = pkgs.lib.recurseIntoAttrs {
2067 inherit (pkgs) hello figlet;
2076 attrs // { recurseForDerivations = true; };
2079 Undo the effect of recurseIntoAttrs.
2086 : An attribute set to not scan for derivations.
2091 dontRecurseIntoAttrs :: AttrSet -> AttrSet
2094 dontRecurseIntoAttrs =
2096 attrs // { recurseForDerivations = false; };
2099 `unionOfDisjoint x y` is equal to `x // y // z` where the
2100 attrnames in `z` are the intersection of the attrnames in `x` and
2101 `y`, and all values `assert` with an error message. This
2102 operator is commutative, unlike (//).
2109 : 1\. Function argument
2113 : 2\. Function argument
2118 unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
2121 unionOfDisjoint = x: y:
2123 intersection = builtins.intersectAttrs x y;
2124 collisions = lib.concatStringsSep " " (builtins.attrNames intersection);
2125 mask = builtins.mapAttrs (name: value: builtins.throw
2126 "unionOfDisjoint: collision on ${name}; complete list: ${collisions}")
2133 "lib.zipWithNames is a deprecated alias of lib.zipAttrsWithNames." zipAttrsWithNames;
2137 "lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;
2140 cartesianProductOfSets = warnIf (oldestSupportedReleaseIsAtLeast 2405)
2141 "lib.cartesianProductOfSets is a deprecated alias of lib.cartesianProduct." cartesianProduct;