Small discrepancy in pill 7.7
MathiasMalandain opened this issue · comments
Issue
Pill 7.7 explains how line 1 of simple.nix
uses a with
statement for getting the derivations imported from nixpkgs
into scope. However, the actual code of simple.nix
relies on a let
-expression instead.
Possible fixes
- Just rewrite, either the text itself, or the
simple.nix
code. - Bonus points if you do both and explain the differences (if any? still learning my Nix...), but this would maybe bloat this pill a little.
I, for one, think the let
-expression is pretty clear and readable, but, full disclaimer: I am an OCaml programmer.
Footnote
I really enjoy the pills so far, thanks a lot!
Thank you for bringing this issue to our attention, and I'm pleased to hear you've been enjoying the pills so far.
You're correct that there is a discrepancy between the description in Pill 7.7 and the actual code in simple.nix
. I appreciate your patience as we work to align these resources for better understanding. I believe it should be rephrased, indeed, as such:
In the first line of simple.nix, we have an import function. Recall that import accepts one argument, a nix file to load. In this case, the contents of the file evaluated to a function.
Now, Let me explain the differences between using let
and with
:
The let...in
expression:
When we use the let
expression like so: let pkgs = import <nixpkgs> {}; in ...
, we are essentially creating a local variable pkgs
. This variable is then available throughout the rest of the expression defined after the in
keyword.
The with
statement:
An alternative way of bringing nixpkgs
derivations into scope could look something like:
with import <nixpkgs> {};
pkgs.stdenv.mkDerivation { ... }
Using with
in this manner is syntactically valid but can lead to confusion. The with
statement will attempt to bind all unknown variables in the scope to the result of import <nixpkgs> {};
. This behavior could potentially make it difficult to trace the origin of variables, especially for static analysis tools. For these reasons, I generally advise against using with
unless the use case is straightforward and usually with a list, such as: meta.maintainers = with lib.maintainers; [ drupol ];
.
Hope it's clearer!
@MathiasMalandain would be great if you could open a PR to fix the description text. Using the let
expression is definitely the preferred way these days: https://nix.dev/recipes/best-practices#with-scopes
Thanks a lot for the clear, detailed explanations and the link to the "best practices" page.