summary refs log tree commit diff
path: root/lib/lists.nix
diff options
context:
space:
mode:
authorSilvan Mosberger <silvan.mosberger@tweag.io>2023-09-22 02:42:29 +0200
committerSilvan Mosberger <silvan.mosberger@tweag.io>2023-09-27 02:43:36 +0200
commit857a844ea8f1736e42f9c14c992d95be7b83a7c4 (patch)
treebdd7da0d526ae95935ab5c54bceafbbb9e64318f /lib/lists.nix
parent9893fee947ceba487f0475bbecfea6d5959e2e6f (diff)
downloadnixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.tar
nixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.tar.gz
nixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.tar.bz2
nixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.tar.lz
nixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.tar.xz
nixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.tar.zst
nixpkgs-857a844ea8f1736e42f9c14c992d95be7b83a7c4.zip
lib.lists.foldl': Redo documentation
Co-Authored-By: Robert Hensing <robert@roberthensing.nl>
Diffstat (limited to 'lib/lists.nix')
-rw-r--r--lib/lists.nix55
1 files changed, 48 insertions, 7 deletions
diff --git a/lib/lists.nix b/lib/lists.nix
index 4a13550ca9e..8c5099084bb 100644
--- a/lib/lists.nix
+++ b/lib/lists.nix
@@ -86,15 +86,56 @@ rec {
         else op (foldl' (n - 1)) (elemAt list n);
     in foldl' (length list - 1);
 
-  /* Strict version of `foldl`.
+  /*
+    Reduce a list by applying a binary operator from left to right,
+    starting with an initial accumulator.
 
-     The difference is that evaluation is forced upon access. Usually used
-     with small whole results (in contrast with lazily-generated list or large
-     lists where only a part is consumed.)
+    After each application of the operator, the resulting value is evaluated.
+    This behavior makes this function stricter than [`foldl`](#function-library-lib.lists.foldl).
 
-     Type: foldl' :: (b -> a -> b) -> b -> [a] -> b
-  */
-  foldl' = builtins.foldl';
+    A call like
+
+    ```nix
+    foldl' op acc₀ [ x₀ x₁ x₂ ... xₙ₋₁ xₙ ]
+    ```
+
+    is (denotationally) equivalent to the following,
+    but with the added benefit that `foldl'` itself will never overflow the stack.
+
+    ```nix
+    let
+      acc₁   =                      op acc₀   x₀   ;
+      acc₂   = builtins.seq acc₁   (op acc₁   x₁  );
+      acc₃   = builtins.seq acc₂   (op acc₂   x₂  );
+      ...
+      accₙ   = builtins.seq accₙ₋₁ (op accₙ₋₁ xₙ₋₁);
+      accₙ₊₁ = builtins.seq accₙ   (op accₙ   xₙ  );
+    in
+    accₙ₊₁
+
+    # Or ignoring builtins.seq
+    op (op (... (op (op (op acc₀ x₀) x₁) x₂) ...) xₙ₋₁) xₙ
+    ```
+
+    Type: foldl' :: (acc -> x -> acc) -> acc -> [x] -> acc
+
+    Example:
+      foldl' (acc: x: acc + x) 0 [1 2 3]
+      => 6
+  */
+  foldl' =
+    /* The binary operation to run, where the two arguments are:
+
+    1. `acc`: The current accumulator value: Either the initial one for the first iteration, or the result of the previous iteration
+    2. `x`: The corresponding list element for this iteration
+    */
+    op:
+    # The initial accumulator value
+    acc:
+    # The list to fold
+    list:
+
+    builtins.foldl' op acc list;
 
   /* Map with index starting from 0