From 15a8d05ba592355f37442743bb3ce9fe55b72911 Mon Sep 17 00:00:00 2001 From: hsjobeki Date: Tue, 28 Feb 2023 11:04:19 +0100 Subject: init: lib.foldlAttrs - provide comprehensive example - add unit test --- lib/attrsets.nix | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'lib/attrsets.nix') diff --git a/lib/attrsets.nix b/lib/attrsets.nix index 30952651adf4..d9a6eab0603e 100644 --- a/lib/attrsets.nix +++ b/lib/attrsets.nix @@ -333,6 +333,66 @@ rec { ) (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. Example: -- cgit 1.4.1