The thing about shadowing is that `with` will not shadow anything that's in the implicit context, which includes things defined by `let` (hence why I avoid it) and function arguments (unavoidable). We can shadow other `with` bindings as much as we like, e.g.
with { foo = 1; };
with { foo = 2; };
with { foo = 3; };
with { bar = with { foo = 4; }; foo; };
[ foo bar ]
This evaluates to [ 3 4 ], since later bindings to `foo` will shadow/override earlier ones.
This doesn't work for bindings that are in the implicit environment/context, for example:
with {
f = foo: with { foo = 42; }; foo;
};
f 123
This evaluates to 123, since the binding `with { foo = 42; }; ...` doesn't shadow/override the argument `foo`.
The rationale for this behaviour is to avoid changes made to an attrset from overriding explicit arguments. For example:
foo:
with bar;
x + foo
This is presumably meant to behave like `foo: bar.x + foo`, but a future change to `bar` might include a `bar.foo` attribute, in which case we don't want the above to change behaviour to `foo: bar.x + bar.foo`.
I understand this rationale, especially when using huge, constantly-changing attrsets like `with nixpkgs; ...`, but it's still annoying ;)
The thing about shadowing is that `with` will not shadow anything that's in the implicit context, which includes things defined by `let` (hence why I avoid it) and function arguments (unavoidable). We can shadow other `with` bindings as much as we like, e.g.
This evaluates to [ 3 4 ], since later bindings to `foo` will shadow/override earlier ones.This doesn't work for bindings that are in the implicit environment/context, for example:
This evaluates to 123, since the binding `with { foo = 42; }; ...` doesn't shadow/override the argument `foo`.The rationale for this behaviour is to avoid changes made to an attrset from overriding explicit arguments. For example:
This is presumably meant to behave like `foo: bar.x + foo`, but a future change to `bar` might include a `bar.foo` attribute, in which case we don't want the above to change behaviour to `foo: bar.x + bar.foo`.I understand this rationale, especially when using huge, constantly-changing attrsets like `with nixpkgs; ...`, but it's still annoying ;)