NixOS / nix-pills

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.