2 Operations on attribute sets.
7 inherit (builtins) head length;
8 inherit (lib.trivial) mergeAttrs warn;
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;
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 cartesianProductOfSets :: AttrSet -> [AttrSet]
893 ## `lib.attrsets.cartesianProductOfSets` usage example
896 cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
907 cartesianProductOfSets =
909 foldl' (listOfAttrs: attrName:
911 map (listValue: attrs // { ${attrName} = listValue; }) attrsOfLists.${attrName}
913 ) [{}] (attrNames attrsOfLists);
917 Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
933 nameValuePair :: String -> Any -> { name :: String; value :: Any; }
938 ## `lib.attrsets.nameValuePair` usage example
941 nameValuePair "some" 6
942 => { name = "some"; value = 6; }
950 { inherit name value; };
954 Apply a function to each element in an attribute set, creating a new attribute set.
960 : A function that takes an attribute name and its value, and returns the new value for the attribute.
964 : The attribute set to iterate through.
969 mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
974 ## `lib.attrsets.mapAttrs` usage example
977 mapAttrs (name: value: name + "-" + value)
978 { x = "foo"; y = "bar"; }
979 => { x = "x-foo"; y = "y-bar"; }
984 mapAttrs = builtins.mapAttrs;
988 Like `mapAttrs`, but allows the name of each attribute to be
989 changed in addition to the value. The applied function should
990 return both the new name and value as a `nameValuePair`.
997 : A function, given an attribute's name and value, returns a new `nameValuePair`.
1001 : Attribute set to map over.
1006 mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
1011 ## `lib.attrsets.mapAttrs'` usage example
1014 mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
1015 { x = "a"; y = "b"; }
1016 => { foo_x = "bar-a"; foo_y = "bar-b"; }
1024 listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
1028 Call a function for each attribute in the given set and return
1029 the result in a list.
1035 : A function, given an attribute's name and value, returns a new value.
1039 : Attribute set to map over.
1044 mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
1049 ## `lib.attrsets.mapAttrsToList` usage example
1052 mapAttrsToList (name: value: name + value)
1053 { x = "a"; y = "b"; }
1062 map (name: f name attrs.${name}) (attrNames attrs);
1065 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).
1066 Each element of the resulting list is an attribute set with these attributes:
1067 - `name` (string): The name of the attribute
1068 - `value` (any): The value of the attribute
1070 The following is always true:
1072 builtins.listToAttrs (attrsToList attrs) == attrs
1076 The opposite is not always true. In general expect that
1078 attrsToList (builtins.listToAttrs list) != list
1081 This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
1088 : The attribute set to deconstruct.
1093 attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
1098 ## `lib.attrsets.attrsToList` usage example
1101 attrsToList { foo = 1; bar = "asdf"; }
1102 => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
1107 attrsToList = mapAttrsToList nameValuePair;
1111 Like `mapAttrs`, except that it recursively applies itself to the *leaf* attributes of a potentially-nested attribute set:
1112 the second argument of the function will never be an attrset.
1113 Also, the first argument of the mapping function is a *list* of the attribute names that form the path to the leaf attribute.
1115 For a function that gives you control over what counts as a leaf, see `mapAttrsRecursiveCond`.
1117 :::{#map-attrs-recursive-example .example}
1118 # Map over leaf attributes
1121 mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value]))
1122 { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; }
1126 { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; }
1132 mapAttrsRecursive :: ([String] -> a -> b) -> AttrSet -> AttrSet
1138 mapAttrsRecursiveCond (as: true) f set;
1142 Like `mapAttrsRecursive`, but it takes an additional predicate that tells it whether to recurse into an attribute set.
1143 If the predicate returns false, `mapAttrsRecursiveCond` does not recurse, but instead applies the mapping function.
1144 If the predicate returns true, it does recurse, and does not apply the mapping function.
1146 :::{#map-attrs-recursive-cond-example .example}
1147 # Map over an leaf attributes defined by a condition
1149 Map derivations to their `name` attribute.
1150 Derivatons are identified as attribute sets that contain `{ type = "derivation"; }`.
1152 mapAttrsRecursiveCond
1153 (as: !(as ? "type" && as.type == "derivation"))
1161 mapAttrsRecursiveCond :: (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet
1164 mapAttrsRecursiveCond =
1172 if isAttrs value && cond value
1173 then recurse (path ++ [ name ]) value
1174 else f (path ++ [ name ]) value);
1180 Generate an attribute set by mapping a function over a list of
1188 : Names of values in the resulting attribute set.
1192 : A function, given the name of the attribute, returns the attribute's value.
1197 genAttrs :: [ String ] -> (String -> Any) -> AttrSet
1202 ## `lib.attrsets.genAttrs` usage example
1205 genAttrs [ "foo" "bar" ] (name: "x_" + name)
1206 => { foo = "x_foo"; bar = "x_bar"; }
1214 listToAttrs (map (n: nameValuePair n (f n)) names);
1218 Check whether the argument is a derivation. Any set with
1219 `{ type = "derivation"; }` counts as a derivation.
1231 isDerivation :: Any -> Bool
1236 ## `lib.attrsets.isDerivation` usage example
1239 nixpkgs = import <nixpkgs> {}
1240 isDerivation nixpkgs.ruby
1242 isDerivation "foobar"
1249 value: value.type or null == "derivation";
1252 Converts a store path to a fake derivation.
1259 : A store path to convert to a derivation.
1264 toDerivation :: Path -> Derivation
1270 path' = builtins.storePath path;
1272 { type = "derivation";
1273 name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path'));
1275 outputs = [ "out" ];
1283 If `cond` is true, return the attribute set `as`,
1284 otherwise an empty attribute set.
1291 : Condition under which the `as` attribute set is returned.
1295 : The attribute set to return if `cond` is `true`.
1300 optionalAttrs :: Bool -> AttrSet -> AttrSet
1305 ## `lib.attrsets.optionalAttrs` usage example
1308 optionalAttrs (true) { my = "set"; }
1310 optionalAttrs (false) { my = "set"; }
1319 if cond then as else {};
1323 Merge sets of attributes and use the function `f` to merge attributes
1331 : List of attribute names to zip.
1335 : A function, accepts an attribute name, all the values, and returns a combined value.
1339 : List of values from the list of attribute sets.
1344 zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1349 ## `lib.attrsets.zipAttrsWithNames` usage example
1352 zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
1353 => { a = ["x" "y"]; }
1362 listToAttrs (map (name: {
1364 value = f name (catAttrs name sets);
1369 Merge sets of attributes and use the function f to merge attribute values.
1370 Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
1372 Implementation note: Common names appear multiple times in the list of
1373 names, hopefully this does not affect the system because the maximal
1374 laziness avoid computing twice the same expression and `listToAttrs` does
1375 not care about duplicated attribute names.
1380 zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
1385 ## `lib.attrsets.zipAttrsWith` usage example
1388 zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
1389 => { a = ["x" "y"]; b = ["z"]; }
1395 builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
1399 Merge sets of attributes and combine each attribute value in to a list.
1401 Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
1406 zipAttrs :: [ AttrSet ] -> AttrSet
1411 ## `lib.attrsets.zipAttrs` usage example
1414 zipAttrs [{a = "x";} {a = "y"; b = "z";}]
1415 => { a = ["x" "y"]; b = ["z"]; }
1420 zipAttrs = zipAttrsWith (name: values: values);
1423 Merge a list of attribute sets together using the `//` operator.
1424 In case of duplicate attributes, values from later list elements take precedence over earlier ones.
1425 The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
1426 For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
1433 : 1\. Function argument
1438 mergeAttrsList :: [ Attrs ] -> Attrs
1443 ## `lib.attrsets.mergeAttrsList` usage example
1446 mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
1447 => { a = 0; b = 1; c = 2; d = 3; }
1448 mergeAttrsList [ { a = 0; } { a = 1; } ]
1454 mergeAttrsList = list:
1456 # `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end`
1457 # Type: Int -> Int -> Attrs
1458 binaryMerge = start: end:
1459 # assert start < end; # Invariant
1460 if end - start >= 2 then
1461 # If there's at least 2 elements, split the range in two, recurse on each part and merge the result
1462 # The invariant is satisfied because each half will have at least 1 element
1463 binaryMerge start (start + (end - start) / 2)
1464 // binaryMerge (start + (end - start) / 2) end
1466 # Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly
1470 # Calling binaryMerge as below would not satisfy its invariant
1473 binaryMerge 0 (length list);
1477 Does the same as the update operator '//' except that attributes are
1478 merged until the given predicate is verified. The predicate should
1479 accept 3 arguments which are the path to reach the attribute, a part of
1480 the first attribute set and a part of the second attribute set. When
1481 the predicate is satisfied, the value of the first attribute set is
1482 replaced by the value of the second attribute set.
1489 : 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.
1493 : Left attribute set of the merge.
1497 : Right attribute set of the merge.
1502 recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
1507 ## `lib.attrsets.recursiveUpdateUntil` usage example
1510 recursiveUpdateUntil (path: l: r: path == ["foo"]) {
1511 # first attribute set
1516 #second attribute set
1523 foo.bar = 1; # 'foo.*' from the second set
1525 bar = 3; # 'bar' from the first set
1526 baz = 4; # 'baz' from the second set
1532 recursiveUpdateUntil =
1537 zipAttrsWith (n: values:
1538 let here = attrPath ++ [n]; in
1539 if length values == 1
1540 || pred here (elemAt values 1) (head values) then
1549 A recursive variant of the update operator ‘//’. The recursion
1550 stops when one of the attribute values is not an attribute set,
1551 in which case the right hand side value takes precedence over the
1552 left hand side value.
1559 : Left attribute set of the merge.
1563 : Right attribute set of the merge.
1568 recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
1573 ## `lib.attrsets.recursiveUpdate` usage example
1577 boot.loader.grub.enable = true;
1578 boot.loader.grub.device = "/dev/hda";
1580 boot.loader.grub.device = "";
1584 boot.loader.grub.enable = true;
1585 boot.loader.grub.device = "";
1594 recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
1598 Recurse into every attribute set of the first argument and check that:
1599 - Each attribute path also exists in the second argument.
1600 - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
1607 : Attribute set structure to match
1611 : Attribute set to check
1616 matchAttrs :: AttrSet -> AttrSet -> Bool
1621 ## `lib.attrsets.matchAttrs` usage example
1624 matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
1633 assert isAttrs pattern;
1635 ( # Compare equality between `pattern` & `attrs`.
1637 # Missing attr, not equal.
1638 attrs ? ${attr} && (
1640 lhs = pattern.${attr};
1641 rhs = attrs.${attr};
1643 # If attrset check recursively
1644 if isAttrs lhs then isAttrs rhs && matchAttrs lhs rhs
1648 (attrNames pattern);
1651 Override only the attributes that are already present in the old set
1652 useful for deep-overriding.
1659 : Original attribute set
1663 : Attribute set with attributes to override in `old`.
1668 overrideExisting :: AttrSet -> AttrSet -> AttrSet
1673 ## `lib.attrsets.overrideExisting` usage example
1676 overrideExisting {} { a = 1; }
1678 overrideExisting { b = 2; } { a = 1; }
1680 overrideExisting { a = 3; b = 2; } { a = 1; }
1681 => { a = 1; b = 2; }
1689 mapAttrs (name: value: new.${name} or value) old;
1693 Turns a list of strings into a human-readable description of those
1694 strings represented as an attribute path. The result of this function is
1695 not intended to be machine-readable.
1696 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
1703 : Attribute path to render to a string
1708 showAttrPath :: [String] -> String
1713 ## `lib.attrsets.showAttrPath` usage example
1716 showAttrPath [ "foo" "10" "bar" ]
1719 => "<root attribute path>"
1726 if path == [] then "<root attribute path>"
1727 else concatMapStringsSep "." escapeNixIdentifier path;
1731 Get a package output.
1732 If no output is found, fallback to `.out` and then to the default.
1739 : 1\. Function argument
1743 : 2\. Function argument
1748 getOutput :: String -> Derivation -> String
1753 ## `lib.attrsets.getOutput` usage example
1756 getOutput "dev" pkgs.openssl
1757 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1762 getOutput = output: pkg:
1763 if ! pkg ? outputSpecified || ! pkg.outputSpecified
1764 then pkg.${output} or pkg.out or pkg
1768 Get a package's `bin` output.
1769 If the output does not exist, fallback to `.out` and then to the default.
1775 : The package whose `bin` output will be retrieved.
1780 getBin :: Derivation -> String
1785 ## `lib.attrsets.getBin` usage example
1789 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
1794 getBin = getOutput "bin";
1798 Get a package's `lib` output.
1799 If the output does not exist, fallback to `.out` and then to the default.
1805 : The package whose `lib` output will be retrieved.
1810 getLib :: Derivation -> String
1815 ## `lib.attrsets.getLib` usage example
1819 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
1824 getLib = getOutput "lib";
1828 Get a package's `dev` output.
1829 If the output does not exist, fallback to `.out` and then to the default.
1835 : The package whose `dev` output will be retrieved.
1840 getDev :: Derivation -> String
1845 ## `lib.attrsets.getDev` usage example
1849 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
1854 getDev = getOutput "dev";
1858 Get a package's `man` output.
1859 If the output does not exist, fallback to `.out` and then to the default.
1865 : The package whose `man` output will be retrieved.
1870 getMan :: Derivation -> String
1875 ## `lib.attrsets.getMan` usage example
1879 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
1884 getMan = getOutput "man";
1887 Pick the outputs of packages to place in `buildInputs`
1898 chooseDevOutputs :: [Derivation] -> [String]
1901 chooseDevOutputs = builtins.map getDev;
1904 Make various Nix tools consider the contents of the resulting
1905 attribute set when looking for what to build, find, etc.
1907 This function only affects a single attribute set; it does not
1908 apply itself recursively for nested attribute sets.
1915 : An attribute set to scan for derivations.
1920 recurseIntoAttrs :: AttrSet -> AttrSet
1925 ## `lib.attrsets.recurseIntoAttrs` usage example
1928 { pkgs ? import <nixpkgs> {} }:
1930 myTools = pkgs.lib.recurseIntoAttrs {
1931 inherit (pkgs) hello figlet;
1940 attrs // { recurseForDerivations = true; };
1943 Undo the effect of recurseIntoAttrs.
1950 : An attribute set to not scan for derivations.
1955 dontRecurseIntoAttrs :: AttrSet -> AttrSet
1958 dontRecurseIntoAttrs =
1960 attrs // { recurseForDerivations = false; };
1963 `unionOfDisjoint x y` is equal to `x // y // z` where the
1964 attrnames in `z` are the intersection of the attrnames in `x` and
1965 `y`, and all values `assert` with an error message. This
1966 operator is commutative, unlike (//).
1973 : 1\. Function argument
1977 : 2\. Function argument
1982 unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
1985 unionOfDisjoint = x: y:
1987 intersection = builtins.intersectAttrs x y;
1988 collisions = lib.concatStringsSep " " (builtins.attrNames intersection);
1989 mask = builtins.mapAttrs (name: value: builtins.throw
1990 "unionOfDisjoint: collision on ${name}; complete list: ${collisions}")
1997 "lib.zipWithNames is a deprecated alias of lib.zipAttrsWithNames." zipAttrsWithNames;
2001 "lib.zip is a deprecated alias of lib.zipAttrsWith." zipAttrsWith;