lib/attrsets: document all the functions
This commit is contained in:
parent
a086858ef5
commit
523e328318
133
lib/attrsets.nix
133
lib/attrsets.nix
|
@ -12,9 +12,15 @@ rec {
|
||||||
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr;
|
inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr;
|
||||||
|
|
||||||
|
|
||||||
/* Return an attribute from nested attribute sets. For instance
|
/* Return an attribute from nested attribute sets.
|
||||||
["x" "y"] applied to some set e returns e.x.y, if it exists. The
|
|
||||||
default value is returned otherwise. */
|
Example:
|
||||||
|
x = { a = { b = 3; }; }
|
||||||
|
attrByPath ["a" "b"] 6 x
|
||||||
|
=> 3
|
||||||
|
attrByPath ["z" "z"] 6 x
|
||||||
|
=> 6
|
||||||
|
*/
|
||||||
attrByPath = attrPath: default: e:
|
attrByPath = attrPath: default: e:
|
||||||
let attr = head attrPath;
|
let attr = head attrPath;
|
||||||
in
|
in
|
||||||
|
@ -24,8 +30,15 @@ rec {
|
||||||
else default;
|
else default;
|
||||||
|
|
||||||
/* Return if an attribute from nested attribute set exists.
|
/* Return if an attribute from nested attribute set exists.
|
||||||
For instance ["x" "y"] applied to some set e returns true, if e.x.y exists. False
|
|
||||||
is returned otherwise. */
|
Example:
|
||||||
|
x = { a = { b = 3; }; }
|
||||||
|
hasAttrByPath ["a" "b"] x
|
||||||
|
=> true
|
||||||
|
hasAttrByPath ["z" "z"] x
|
||||||
|
=> false
|
||||||
|
|
||||||
|
*/
|
||||||
hasAttrByPath = attrPath: e:
|
hasAttrByPath = attrPath: e:
|
||||||
let attr = head attrPath;
|
let attr = head attrPath;
|
||||||
in
|
in
|
||||||
|
@ -35,14 +48,28 @@ rec {
|
||||||
else false;
|
else false;
|
||||||
|
|
||||||
|
|
||||||
/* Return nested attribute set in which an attribute is set. For instance
|
/* Return nested attribute set in which an attribute is set.
|
||||||
["x" "y"] applied with some value v returns `x.y = v;' */
|
|
||||||
|
Example:
|
||||||
|
setAttrByPath ["a" "b"] 3
|
||||||
|
=> { a = { b = 3; }; }
|
||||||
|
*/
|
||||||
setAttrByPath = attrPath: value:
|
setAttrByPath = attrPath: value:
|
||||||
if attrPath == [] then value
|
if attrPath == [] then value
|
||||||
else listToAttrs
|
else listToAttrs
|
||||||
[ { name = head attrPath; value = setAttrByPath (tail attrPath) value; } ];
|
[ { name = head attrPath; value = setAttrByPath (tail attrPath) value; } ];
|
||||||
|
|
||||||
|
|
||||||
|
/* Like `getAttrPath' without a default value. If it doesn't find the
|
||||||
|
path it will throw.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
x = { a = { b = 3; }; }
|
||||||
|
getAttrFromPath ["a" "b"] x
|
||||||
|
=> 3
|
||||||
|
getAttrFromPath ["z" "z"] x
|
||||||
|
=> error: cannot find attribute `z.z'
|
||||||
|
*/
|
||||||
getAttrFromPath = attrPath: set:
|
getAttrFromPath = attrPath: set:
|
||||||
let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'";
|
let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'";
|
||||||
in attrByPath attrPath (abort errorMsg) set;
|
in attrByPath attrPath (abort errorMsg) set;
|
||||||
|
@ -109,7 +136,9 @@ rec {
|
||||||
) (attrNames set)
|
) (attrNames set)
|
||||||
);
|
);
|
||||||
|
|
||||||
/* foldAttrs: apply fold functions to values grouped by key. Eg accumulate values as list:
|
/* Apply fold functions to values grouped by key.
|
||||||
|
|
||||||
|
Example:
|
||||||
foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }]
|
foldAttrs (n: a: [n] ++ a) [] [{ a = 2; } { a = 3; }]
|
||||||
=> { a = [ 2 3 ]; }
|
=> { a = [ 2 3 ]; }
|
||||||
*/
|
*/
|
||||||
|
@ -147,7 +176,12 @@ rec {
|
||||||
|
|
||||||
|
|
||||||
/* Utility function that creates a {name, value} pair as expected by
|
/* Utility function that creates a {name, value} pair as expected by
|
||||||
builtins.listToAttrs. */
|
builtins.listToAttrs.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
nameValuePair "some" 6
|
||||||
|
=> { name = "some"; value = 6; }
|
||||||
|
*/
|
||||||
nameValuePair = name: value: { inherit name value; };
|
nameValuePair = name: value: { inherit name value; };
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,11 +282,19 @@ rec {
|
||||||
listToAttrs (map (n: nameValuePair n (f n)) names);
|
listToAttrs (map (n: nameValuePair n (f n)) names);
|
||||||
|
|
||||||
|
|
||||||
/* Check whether the argument is a derivation. */
|
/* Check whether the argument is a derivation. Any set with
|
||||||
|
{ type = "derivation"; } counts as a derivation.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
nixpkgs = import <nixpkgs> {}
|
||||||
|
isDerivation nixpkgs.ruby
|
||||||
|
=> true
|
||||||
|
isDerivation "foobar"
|
||||||
|
=> false
|
||||||
|
*/
|
||||||
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
|
isDerivation = x: isAttrs x && x ? type && x.type == "derivation";
|
||||||
|
|
||||||
|
/* Converts a store path to a fake derivation. */
|
||||||
/* Convert a store path to a fake derivation. */
|
|
||||||
toDerivation = path:
|
toDerivation = path:
|
||||||
let path' = builtins.storePath path; in
|
let path' = builtins.storePath path; in
|
||||||
{ type = "derivation";
|
{ type = "derivation";
|
||||||
|
@ -262,32 +304,49 @@ rec {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* If the Boolean `cond' is true, return the attribute set `as',
|
/* If `cond' is true, return the attribute set `as',
|
||||||
otherwise an empty attribute set. */
|
otherwise an empty attribute set.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
optionalAttrs (true) { my = "set"; }
|
||||||
|
=> { my = "set"; }
|
||||||
|
optionalAttrs (false) { my = "set"; }
|
||||||
|
=> { }
|
||||||
|
*/
|
||||||
optionalAttrs = cond: as: if cond then as else {};
|
optionalAttrs = cond: as: if cond then as else {};
|
||||||
|
|
||||||
|
|
||||||
/* Merge sets of attributes and use the function f to merge attributes
|
/* Merge sets of attributes and use the function f to merge attributes
|
||||||
values. */
|
values.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
|
||||||
|
=> { a = ["x" "y"]; }
|
||||||
|
*/
|
||||||
zipAttrsWithNames = names: f: sets:
|
zipAttrsWithNames = names: f: sets:
|
||||||
listToAttrs (map (name: {
|
listToAttrs (map (name: {
|
||||||
inherit name;
|
inherit name;
|
||||||
value = f name (catAttrs name sets);
|
value = f name (catAttrs name sets);
|
||||||
}) names);
|
}) names);
|
||||||
|
|
||||||
# implentation note: Common names appear multiple times in the list of
|
/* Implentation note: Common names appear multiple times in the list of
|
||||||
# names, hopefully this does not affect the system because the maximal
|
names, hopefully this does not affect the system because the maximal
|
||||||
# laziness avoid computing twice the same expression and listToAttrs does
|
laziness avoid computing twice the same expression and listToAttrs does
|
||||||
# not care about duplicated attribute names.
|
not care about duplicated attribute names.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
|
||||||
|
=> { a = ["x" "y"]; b = ["z"] }
|
||||||
|
*/
|
||||||
zipAttrsWith = f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets;
|
zipAttrsWith = f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets;
|
||||||
|
/* Like `zipAttrsWith' with `(name: values: value)' as the function.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
zipAttrs [{a = "x";} {a = "y"; b = "z";}]
|
||||||
|
=> { a = ["x" "y"]; b = ["z"] }
|
||||||
|
*/
|
||||||
zipAttrs = zipAttrsWith (name: values: values);
|
zipAttrs = zipAttrsWith (name: values: values);
|
||||||
|
|
||||||
/* backward compatibility */
|
|
||||||
zipWithNames = zipAttrsWithNames;
|
|
||||||
zip = builtins.trace "lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith;
|
|
||||||
|
|
||||||
|
|
||||||
/* Does the same as the update operator '//' except that attributes are
|
/* Does the same as the update operator '//' except that attributes are
|
||||||
merged until the given pedicate is verified. The predicate should
|
merged until the given pedicate is verified. The predicate should
|
||||||
accept 3 arguments which are the path to reach the attribute, a part of
|
accept 3 arguments which are the path to reach the attribute, a part of
|
||||||
|
@ -351,6 +410,15 @@ rec {
|
||||||
!(isAttrs lhs && isAttrs rhs)
|
!(isAttrs lhs && isAttrs rhs)
|
||||||
) lhs rhs;
|
) lhs rhs;
|
||||||
|
|
||||||
|
/* Returns true if the pattern is contained in the set. False otherwise.
|
||||||
|
|
||||||
|
FIXME(zimbatm): this example doesn't work !!!
|
||||||
|
|
||||||
|
Example:
|
||||||
|
sys = mkSystem { }
|
||||||
|
matchAttrs { cpu = { bits = 64; }; } sys
|
||||||
|
=> true
|
||||||
|
*/
|
||||||
matchAttrs = pattern: attrs:
|
matchAttrs = pattern: attrs:
|
||||||
fold or false (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
|
fold or false (attrValues (zipAttrsWithNames (attrNames pattern) (n: values:
|
||||||
let pat = head values; val = head (tail values); in
|
let pat = head values; val = head (tail values); in
|
||||||
|
@ -359,10 +427,23 @@ rec {
|
||||||
else pat == val
|
else pat == val
|
||||||
) [pattern attrs]));
|
) [pattern attrs]));
|
||||||
|
|
||||||
# override only the attributes that are already present in the old set
|
/* Override only the attributes that are already present in the old set
|
||||||
# useful for deep-overriding
|
useful for deep-overriding.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
x = { a = { b = 4; c = 3; }; }
|
||||||
|
overrideExisting x { a = { b = 6; d = 2; }; }
|
||||||
|
=> { a = { b = 6; d = 2; }; }
|
||||||
|
*/
|
||||||
overrideExisting = old: new:
|
overrideExisting = old: new:
|
||||||
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old));
|
old // listToAttrs (map (attr: nameValuePair attr (attrByPath [attr] old.${attr} new)) (attrNames old));
|
||||||
|
|
||||||
|
|
||||||
|
/*** deprecated stuff ***/
|
||||||
|
|
||||||
deepSeqAttrs = throw "removed 2016-02-29 because unused and broken";
|
deepSeqAttrs = throw "removed 2016-02-29 because unused and broken";
|
||||||
|
zipWithNames = zipAttrsWithNames;
|
||||||
|
zip = builtins.trace
|
||||||
|
"lib.zip is deprecated, use lib.zipAttrsWith instead" zipAttrsWith;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue