From b53ef575548dc53dd39bbe75e2a00b26d943f161 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 10 Mar 2009 15:18:38 +0000 Subject: [PATCH] * Moved mapAttrs to attrsets.nix. * Added a function mapAttrsRecursive, which is like mapAttrs, but recursively applies itself to attribute sets. * Commented and cleaned up some functions. svn path=/nixpkgs/trunk/; revision=14495 --- pkgs/lib/attrsets.nix | 90 +++++++++++++++++++++++++++++++++++++------ pkgs/lib/misc.nix | 16 +++----- 2 files changed, 84 insertions(+), 22 deletions(-) diff --git a/pkgs/lib/attrsets.nix b/pkgs/lib/attrsets.nix index a394ff5bd18..dba58f00789 100644 --- a/pkgs/lib/attrsets.nix +++ b/pkgs/lib/attrsets.nix @@ -3,16 +3,18 @@ with { inherit (builtins) head tail; inherit (import ./default.nix) fold; + inherit (import ./strings.nix) concatStringsSep; }; rec { inherit (builtins) attrNames listToAttrs hasAttr isAttrs; - # Return an attribute from nested attribute sets. For instance ["x" - # "y"] applied to some set e returns e.x.y, if it exists. The - # default value is returned otherwise. !!! there is also - # builtins.getAttr (is there a better name for this function?) + /* Return an attribute from nested attribute sets. For instance + ["x" "y"] applied to some set e returns e.x.y, if it exists. The + default value is returned otherwise. !!! there is also + builtins.getAttr (is there a better name for this function?) + */ getAttr = attrPath: default: e: let attr = head attrPath; in @@ -21,14 +23,80 @@ rec { then getAttr (tail attrPath) default (builtins.getAttr attr e) else default; - # ordered by name - attrValues = attrs: attrVals (__attrNames attrs) attrs; - attrVals = nameList : attrSet : - map (x: builtins.getAttr x attrSet) nameList; + getAttrFromPath = attrPath: set: + let errorMsg = "cannot find attribute `" + concatStringsSep "." attrPath + "'"; + in getAttr attrPath (abort errorMsg) set; + - # iterates over a list of attributes collecting the attribute attr if it exists - catAttrs = attr : l : fold ( s : l : if (hasAttr attr s) then [(builtins.getAttr attr s)] ++ l else l) [] l; + /* Return the specified attributes from a set. + + Example: + attrVals ["a" "b" "c"] as + => [as.a as.b as.c] + */ + attrVals = nameList: set: + map (x: builtins.getAttr x set) nameList; -} \ No newline at end of file + /* Return the values of all attributes in the given set, sorted by + attribute name. + + Example: + attrValues {c = 3; a = 1; b = 2;} + => [1 2 3] + */ + attrValues = attrs: attrVals (attrNames attrs) attrs; + + + /* Collect each attribute named `attr' from a list of attribute + sets. Sets that don't contain the named attribute are ignored. + + Example: + catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}] + => [1 2] + */ + catAttrs = attr: l: fold (s: l: if hasAttr attr s then [(builtins.getAttr attr s)] ++ l else l) [] l; + + + /* Utility function that creates a {name, value} pair as expected by + builtins.listToAttrs. */ + nameValuePair = name: value: { inherit name value; }; + + + /* Apply a function to each element in an attribute set. The + function takes two arguments --- the attribute name and its value + --- and returns the new value for the attribute. The result is a + new attribute set. + + Example: + mapAttrs (name: value: name + "-" + value) + {x = "foo"; y = "bar";} + => {x = "x-foo"; y = "y-bar";} + */ + mapAttrs = f: set: + listToAttrs (map (attr: nameValuePair attr (f attr (builtins.getAttr attr set))) (attrNames set)); + + + /* Like `mapAttrs', except that it recursively applies itself to + values that attribute sets. Also, the first argument is a *list* + of the names of the containing attributes. + + Example: + mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value])) + { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; } + => { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; } + */ + mapAttrsRecursive = + let + recurse = path: f: set: + let + g = + name: value: + if isAttrs value + then recurse (path ++ [name]) f value + else f (path ++ [name]) value; + in mapAttrs g set; + in recurse []; + +} diff --git a/pkgs/lib/misc.nix b/pkgs/lib/misc.nix index aa0f29e3651..21dd6d6c034 100644 --- a/pkgs/lib/misc.nix +++ b/pkgs/lib/misc.nix @@ -236,14 +236,8 @@ rec { # should be renamed to mapAttrsFlatten mapRecordFlatten = f : r : map (attr: f attr (builtins.getAttr attr r) ) (attrNames r); - # maps a function on each attr value - # f = attr : value : .. - mapAttrs = f : r : listToAttrs ( mapRecordFlatten (a : v : nv a ( f a v ) ) r); - - # to be used with listToAttrs (_a_ttribute _v_alue) - nv = name : value : { inherit name value; }; # attribute set containing one attribute - nvs = name : value : listToAttrs [ (nv name value) ]; + nvs = name : value : listToAttrs [ (nameValuePair name value) ]; # adds / replaces an attribute of an attribute set setAttr = set : name : v : set // (nvs name v); @@ -322,8 +316,8 @@ rec { mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; }; # sane defaults (same name as attr name so that inherit can be used) mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; } - listToAttrs (map (n : nv n lib.concat) [ "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" ]) - // listToAttrs (map (n : nv n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ]); + listToAttrs (map (n : nameValuePair n lib.concat) [ "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" ]) + // listToAttrs (map (n : nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ]); # returns atribute values as a list flattenAttrs = set : map ( attr : builtins.getAttr attr set) (attrNames set); @@ -332,7 +326,7 @@ rec { # pick attrs subset_attr_names and apply f subsetmap = f : attrs : subset_attr_names : listToAttrs (fold ( attr : r : if __hasAttr attr attrs - then r ++ [ ( nv attr ( f (__getAttr attr attrs) ) ) ] else r ) [] + then r ++ [ ( nameValuePair attr ( f (__getAttr attr attrs) ) ) ] else r ) [] subset_attr_names ); # prepareDerivationArgs tries to make writing configurable derivations easier @@ -372,7 +366,7 @@ rec { prepareDerivationArgs = args: let args2 = { cfg = {}; flags = {}; } // args; flagName = name : "${name}Support"; - cfgWithDefaults = (listToAttrs (map (n : nv (flagName n) false) (attrNames args2.flags))) + cfgWithDefaults = (listToAttrs (map (n : nameValuePair (flagName n) false) (attrNames args2.flags))) // args2.cfg; opts = flattenAttrs (mapAttrs (a : v : let v2 = if (v ? set || v ? unset) then v else { set = v; };