Merge pull request #218776 from hsjobeki/feature/lib-reduceAttrs
add: lib.foldlAttrs
This commit is contained in:
commit
4635079f53
@ -333,6 +333,66 @@ rec {
|
|||||||
) (attrNames set)
|
) (attrNames set)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Like builtins.foldl' but for attribute sets.
|
||||||
|
Iterates over every name-value pair in the given attribute set.
|
||||||
|
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`.
|
||||||
|
|
||||||
|
Attention:
|
||||||
|
There is a completely different function
|
||||||
|
`lib.foldAttrs`
|
||||||
|
which has nothing to do with this function, despite the similar name.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
foldlAttrs
|
||||||
|
(acc: name: value: {
|
||||||
|
sum = acc.sum + value;
|
||||||
|
names = acc.names ++ [name];
|
||||||
|
})
|
||||||
|
{ sum = 0; names = []; }
|
||||||
|
{
|
||||||
|
foo = 1;
|
||||||
|
bar = 10;
|
||||||
|
}
|
||||||
|
->
|
||||||
|
{
|
||||||
|
sum = 11;
|
||||||
|
names = ["bar" "foo"];
|
||||||
|
}
|
||||||
|
|
||||||
|
foldlAttrs
|
||||||
|
(throw "function not needed")
|
||||||
|
123
|
||||||
|
{};
|
||||||
|
->
|
||||||
|
123
|
||||||
|
|
||||||
|
foldlAttrs
|
||||||
|
(_: _: v: v)
|
||||||
|
(throw "initial accumulator not needed")
|
||||||
|
{ z = 3; a = 2; };
|
||||||
|
->
|
||||||
|
3
|
||||||
|
|
||||||
|
The accumulator doesn't have to be an attrset.
|
||||||
|
It can be as simple as a number or string.
|
||||||
|
|
||||||
|
foldlAttrs
|
||||||
|
(acc: _: v: acc * 10 + v)
|
||||||
|
1
|
||||||
|
{ z = 1; a = 2; };
|
||||||
|
->
|
||||||
|
121
|
||||||
|
|
||||||
|
Type:
|
||||||
|
foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
|
||||||
|
*/
|
||||||
|
foldlAttrs = f: init: set:
|
||||||
|
foldl'
|
||||||
|
(acc: name: f acc name set.${name})
|
||||||
|
init
|
||||||
|
(attrNames set);
|
||||||
|
|
||||||
/* Apply fold functions to values grouped by key.
|
/* Apply fold functions to values grouped by key.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -78,7 +78,7 @@ let
|
|||||||
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
|
composeManyExtensions makeExtensible makeExtensibleWithCustomName;
|
||||||
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
|
inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
|
||||||
getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
|
getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
|
||||||
filterAttrsRecursive foldAttrs collect nameValuePair mapAttrs
|
filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs
|
||||||
mapAttrs' mapAttrsToList concatMapAttrs mapAttrsRecursive mapAttrsRecursiveCond
|
mapAttrs' mapAttrsToList concatMapAttrs mapAttrsRecursive mapAttrsRecursiveCond
|
||||||
genAttrs isDerivation toDerivation optionalAttrs
|
genAttrs isDerivation toDerivation optionalAttrs
|
||||||
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
|
zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
|
||||||
|
@ -533,6 +533,37 @@ runTests {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# code from example
|
||||||
|
testFoldlAttrs = {
|
||||||
|
expr = {
|
||||||
|
example = foldlAttrs
|
||||||
|
(acc: name: value: {
|
||||||
|
sum = acc.sum + value;
|
||||||
|
names = acc.names ++ [ name ];
|
||||||
|
})
|
||||||
|
{ sum = 0; names = [ ]; }
|
||||||
|
{
|
||||||
|
foo = 1;
|
||||||
|
bar = 10;
|
||||||
|
};
|
||||||
|
# should just return the initial value
|
||||||
|
emptySet = foldlAttrs (throw "function not needed") 123 { };
|
||||||
|
# should just evaluate to the last value
|
||||||
|
accNotNeeded = foldlAttrs (_acc: _name: v: v) (throw "accumulator not needed") { z = 3; a = 2; };
|
||||||
|
# the accumulator doesnt have to be an attrset it can be as trivial as being just a number or string
|
||||||
|
trivialAcc = foldlAttrs (acc: _name: v: acc * 10 + v) 1 { z = 1; a = 2; };
|
||||||
|
};
|
||||||
|
expected = {
|
||||||
|
example = {
|
||||||
|
sum = 11;
|
||||||
|
names = [ "bar" "foo" ];
|
||||||
|
};
|
||||||
|
emptySet = 123;
|
||||||
|
accNotNeeded = 3;
|
||||||
|
trivialAcc = 121;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# code from the example
|
# code from the example
|
||||||
testRecursiveUpdateUntil = {
|
testRecursiveUpdateUntil = {
|
||||||
expr = recursiveUpdateUntil (path: l: r: path == ["foo"]) {
|
expr = recursiveUpdateUntil (path: l: r: path == ["foo"]) {
|
||||||
|
Loading…
Reference in New Issue
Block a user