noogle/codemod/test/args.nix
2024-01-07 17:20:35 +01:00

60 lines
1.9 KiB
Nix

{
/*
Reduce a list by applying a binary operator from left to right,
starting with an initial accumulator.
Before each application of the operator, the accumulator value is evaluated.
This behavior makes this function stricter than [`foldl`](#function-library-lib.lists.foldl).
Unlike [`builtins.foldl'`](https://nixos.org/manual/nix/unstable/language/builtins.html#builtins-foldl'),
the initial accumulator argument is evaluated before the first iteration.
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 = 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);
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:
# The builtin `foldl'` is a bit lazier than one might expect.
# See https://github.com/NixOS/nix/pull/7158.
# In particular, the initial accumulator value is not forced before the first iteration starts.
builtins.seq acc
(builtins.foldl' op acc list);
}