From 6b24d7bebe32abc2ff77e875c0d61dcc5ebb45fc Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Mon, 30 Mar 2009 13:19:57 +0000 Subject: [PATCH] * `mapAttrsRecursiveCond', which is like `mapAttrsRecursive' but takes a predicate to tell it whether to recursive into a given attribute set. svn path=/nixpkgs/trunk/; revision=14776 --- pkgs/lib/attrsets.nix | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/pkgs/lib/attrsets.nix b/pkgs/lib/attrsets.nix index dba58f00789..3be143d6a21 100644 --- a/pkgs/lib/attrsets.nix +++ b/pkgs/lib/attrsets.nix @@ -79,24 +79,49 @@ rec { /* 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. + attribute sets. Also, the first argument of the argument + function is a *list* of the names of the containing attributes. + + Type: + mapAttrsRecursive :: + ([String] -> a -> b) -> AttrSet -> AttrSet 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 = + mapAttrsRecursive = mapAttrsRecursiveCond (as: true); + + + /* Like `mapAttrsRecursive', but it takes an additional predicate + function that tells it whether to recursive into an attribute + set. If it returns false, `mapAttrsRecursiveCond' does not + recurse, but does apply the map function. It is returns true, it + does recurse, and does not apply the map function. + + Type: + mapAttrsRecursiveCond :: + (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet + + Example: + # To prevent recursing into derivations (which are attribute + # sets with the attribute "type" equal to "derivation"): + mapAttrsRecursiveCond + (as: !(as ? "type" && as.type == "derivation")) + (x: ... do something ...) + attrs + */ + mapAttrsRecursiveCond = cond: f: set: let - recurse = path: f: set: + recurse = path: set: let g = name: value: - if isAttrs value - then recurse (path ++ [name]) f value + if isAttrs value && cond value + then recurse (path ++ [name]) value else f (path ++ [name]) value; in mapAttrs g set; - in recurse []; + in recurse [] set; }