[Nix-dev] with, ++, //, and laziness
Shea Levy
shea at shealevy.com
Fri Mar 23 19:01:21 CET 2012
Hello,
Based on my understanding of Nix semantics, I expected the following to
all evaluate to 2:
let
a = { c = 1; d = b.c; };
b = a // { c = 2; };
in b.d
let
a = with b; { c = 1; d = c; };
b = a // { c = 2; };
in b.d
with (throw "an error"); 2
with ({a = 2;}); with (throw "an error"); a
Unfortunately, only the first actually does. The second causes nix to
report an infinite recursion, and the third and fourth cause nix to
report an error as thrown. This seems to be because 'with' isn't lazy
enough: It tries to evaluate more of its operand than is strictly
necessary to evaluate the end result. The reason this matters is that I
am trying to remove the use of __overrides in all-packages.nix, but in
order to do so while maintaining the current behavior of
packageOverrides and taking into account the infinite recursion in the
second example above, I will have to prepend 'pkgs' to every package
given on the RHS of an assignment in all-packages. I had hoped that I
could add a 'with pkgs;' to the top of the packages attribute set and
make a few other simple modifications, but alas this seems to be a
blocker. Is there any chance of this 'with' behavior being modified?
IMO, the semantics should be something like: if an identifier is
referenced and it is not in scope, go up the nested 'with' chain and
check if the operand has that identifier as an attribute. If the check
does not evaluate to true (either because the operand doesn't have that
identifier, the evaluator detects infinite recursion, or a 'throw' or
'abort' is evaluated), then check up the 'with' chain until there are no
more nested withs left. Does this make sense?
And while we're talking about making nix more lazy, could we make it so
these terminate?
let
f = list: number:
let newList = [number]; in list ++ (f newList (builtins.add number 1));
in builtins.head (f [] 0)
let
f = attrs: number:
let
newAttrs = builtins.listToAttrs [ { name = "a${number}"; value =
number; } ];
in (f newAttrs (builtins.add number 1)) // attrs;
in (f {} 0).a1
Cheers,
Shea
More information about the nix-dev
mailing list