[Nix-dev] Not understanding evaluation of with inside let
    Harald van Dijk 
    harald at gigawatt.nl
       
    Mon May 16 10:34:49 CEST 2016
    
    
  
On 16/05/16 00:06, Vladimír Čunát wrote:
> It's the plain fact that `with` is "low-priority" in nix. Any identifier
> introduced by `with` is only used if it isn't found elsewhere.
Ah, thanks, and also to Layus for finding relevant code in Nix and 
giving a valid use case for it.
> I agree it can seem confusing, at least at first. I'm not sure if it's
> documented somewhere, but we've had quite a few discussions on that
> topic already.
I guess tests can sort of work as developer documentation, and I've now 
found that tests/lang/eval-okay-with.nix specifically tests this 
behaviour since 2010. Yet when it was first checked in in 2005, it 
tested the behaviour I would have expected. The commit message of the 
change to the test was simply "Doh." I was hoping to get a little bit 
more information there. :)
Documentation would be nice. Starting from what's documented now:
 > With-expressions
 > A with-expression,
 > with e1; e2
 > introduces the set e1 into the lexical scope of the expression e2.
 > For instance,
 > let as = { x = "foo"; y = "bar"; };
 > in with as; x + y
 > evaluates to "foobar" since the with adds the x and y attributes of
 > as to the lexical scope in the expression x + y. The most common use
 > of with is in conjunction with the import function. E.g.,
 > with (import ./definitions.nix); ...
 > makes all attributes defined in the file definitions.nix available as
 > if they were defined locally in a rec-expression.
I think the "as if they were defined locally in a rec-expression" is 
wrong. A rec-expression does not have this special low-priority scoping 
rule. Compare:
   let x = 1; in (rec { x = 2; y = x; }).y
   let x = 1; in with { x = 2; }; x
I think the documentation is saying these give the same result, but they 
don't.
It seems like your wording almost immediately gives a useful tweak and 
addition to this text:
   makes all attributes defined in the file definitions.nix available
   similarly to how a rec-expression would.
   However, the names introduced by with have lower priority than those
   introduced by other means. For instance,
   let as = { x = "foo"; y = "bar"; }; y = "baz";
   in with as; x + y
   evaluates to "foobaz".
Does this look okay?
Cheers,
Harald van Dijk
    
    
More information about the nix-dev
mailing list