about summary refs log tree commit diff
path: root/lib/attrsets.nix
diff options
context:
space:
mode:
authorhsjobeki <hsjobeki+github@gmail.com>2023-02-28 11:04:19 +0100
committerhsjobeki <hsjobeki+github@gmail.com>2023-03-11 10:42:00 +0100
commit15a8d05ba592355f37442743bb3ce9fe55b72911 (patch)
tree98a5da74ced314a9f40f49b4115a89fdd6b38dfc /lib/attrsets.nix
parent624432c25b2044dc291608cd204a7dee5275089b (diff)
init: lib.foldlAttrs
- provide comprehensive example
- add unit test
Diffstat (limited to 'lib/attrsets.nix')
-rw-r--r--lib/attrsets.nix60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/attrsets.nix b/lib/attrsets.nix
index 30952651adf40..d9a6eab0603ed 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: