primops: make nature of foldl' strictness clearer
* Clarify the documentation of foldl': That the arguments are forced before application (?) of `op` is necessarily true. What is important to stress is that we force every application of `op`, even when the value turns out to be unused. * Move the example before the comment about strictness to make it less confusing: It is a general example and doesn't really showcase anything about foldl' strictness. * Add test cases which nail down aspects of foldl' strictness: * The initial accumulator value is not forced unconditionally. * Applications of op are forced. * The list elements are not forced unconditionally.
This commit is contained in:
parent
ac0fb38e8a
commit
d0f2da214b
|
@ -2908,9 +2908,9 @@ static RegisterPrimOp primop_foldlStrict({
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
Reduce a list by applying a binary operator, from left to right,
|
Reduce a list by applying a binary operator, from left to right,
|
||||||
e.g. `foldl' op nul [x0 x1 x2 ...] = op (op (op nul x0) x1) x2)
|
e.g. `foldl' op nul [x0 x1 x2 ...] = op (op (op nul x0) x1) x2)
|
||||||
...`. The operator is applied strictly, i.e., its arguments are
|
...`. For example, `foldl' (x: y: x + y) 0 [1 2 3]` evaluates to 6.
|
||||||
evaluated first. For example, `foldl' (x: y: x + y) 0 [1 2 3]`
|
The return value of each application of `op` is evaluated immediately,
|
||||||
evaluates to 6.
|
even for intermediate values.
|
||||||
)",
|
)",
|
||||||
.fun = prim_foldlStrict,
|
.fun = prim_foldlStrict,
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Tests that the result of applying op is forced even if the value is never used
|
||||||
|
builtins.foldl'
|
||||||
|
(_: f: f null)
|
||||||
|
null
|
||||||
|
[ (_: throw "Not the final value, but is still forced!") (_: 23) ]
|
1
tests/lang/eval-okay-foldlStrict-lazy-elements.exp
Normal file
1
tests/lang/eval-okay-foldlStrict-lazy-elements.exp
Normal file
|
@ -0,0 +1 @@
|
||||||
|
42
|
9
tests/lang/eval-okay-foldlStrict-lazy-elements.nix
Normal file
9
tests/lang/eval-okay-foldlStrict-lazy-elements.nix
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Tests that the rhs argument of op is not forced unconditionally
|
||||||
|
let
|
||||||
|
lst = builtins.foldl'
|
||||||
|
(acc: x: acc ++ [ x ])
|
||||||
|
[ ]
|
||||||
|
[ 42 (throw "this shouldn't be evaluated") ];
|
||||||
|
in
|
||||||
|
|
||||||
|
builtins.head lst
|
|
@ -0,0 +1 @@
|
||||||
|
42
|
|
@ -0,0 +1,6 @@
|
||||||
|
# Checks that the nul value for the accumulator is not forced unconditionally.
|
||||||
|
# Some languages provide a foldl' that is strict in this argument, but Nix does not.
|
||||||
|
builtins.foldl'
|
||||||
|
(_: x: x)
|
||||||
|
(throw "This is never forced")
|
||||||
|
[ "but the results of applying op are" 42 ]
|
Loading…
Reference in a new issue