Describe the bug
I use lib.trivial.pipe from nixpkgs a lot. This is trivially implemented with foldl':
https://github.com/NixOS/nixpkgs/blob/359cc883de993d617ee36df06dbf065e39806a39/lib/trivial.nix#L150
So it came unexpected to me to discover that both functions break lazy evaluation of the intermediates.
I (now) know that this behavior is documented since #9254, and this was documented 5 years after its introduction in 61af14a.
So I tried to search for a reason for this, and have not found one in both PR/commit mentioned above.
As I have found no reason for this behavior, I want to open this issue because I think either a reason for this decision should be documented or that behavior might get changed.
Steps To Reproduce
- save the code below in
test.nix
- run
nix eval --file test.nix
- see the error "this error should not occur"
let
pipe = builtins.foldl' (x: f: f x);
start = [
"hello"
"world"
];
in
pipe start [
(_: abort "this error should not occur")
(builtins.concatStringsSep ", ")
(_: "because this function should prevent its loading")
]
Expected behavior
Return "because this function should prevent its loading", because, in its intention, the code from above should behave the same as:
let
start = [
"hello"
"world"
];
func1 = _: abort "this error should not occur";
func2 = builtins.concatStringsSep ", ";
func3 = _: "because this function should prevent its loading";
in
func3 (func2 (func1 start))
Metadata
From both nix versions I reproduced this:
- nix-env (Nix) 2.31.2
- nix-env (Nix) 2.33.3
Additional context
The code from above is (of course) highly simplified. In my own code, I currently have the problem that because of the "strict" evaluation, an infinite recursion error appears when using pipe. And in that example its way more important to use a pipe construct so the code stays readable.
If for whatever reason (be it backwards compatibility now) you do not want to change this behavior, I’m fine with it. But if this behavior is decided to stay, I would be required to move to using lib.foldl (from nixpkgs) which I expect to perform way worse. And that function should then also be documented to be an explicit "fill-in" for foldl' so it does not get removed in favor of foldl'.
Checklist
Add 👍 to issues you find important.
Describe the bug
I use
lib.trivial.pipefrom nixpkgs a lot. This is trivially implemented withfoldl':https://github.com/NixOS/nixpkgs/blob/359cc883de993d617ee36df06dbf065e39806a39/lib/trivial.nix#L150
So it came unexpected to me to discover that both functions break lazy evaluation of the intermediates.
I (now) know that this behavior is documented since #9254, and this was documented 5 years after its introduction in 61af14a.
So I tried to search for a reason for this, and have not found one in both PR/commit mentioned above.
As I have found no reason for this behavior, I want to open this issue because I think either a reason for this decision should be documented or that behavior might get changed.
Steps To Reproduce
test.nixnix eval --file test.nixExpected behavior
Return
"because this function should prevent its loading", because, in its intention, the code from above should behave the same as:Metadata
From both nix versions I reproduced this:
Additional context
The code from above is (of course) highly simplified. In my own code, I currently have the problem that because of the "strict" evaluation, an infinite recursion error appears when using
pipe. And in that example its way more important to use apipeconstruct so the code stays readable.If for whatever reason (be it backwards compatibility now) you do not want to change this behavior, I’m fine with it. But if this behavior is decided to stay, I would be required to move to using
lib.foldl(from nixpkgs) which I expect to perform way worse. And that function should then also be documented to be an explicit "fill-in" forfoldl'so it does not get removed in favor offoldl'.Checklist
Add 👍 to issues you find important.