So far, I have seen two “flavors” of default.nix/shell.nix files:
-
Function
{pkgs ? import <nixpkgs> {} }: pkgs.mkShell { # declarations }Or, a suggested way when used with
niv:{ sources ? import ./nix/sources.nix , pkgs ? import sources.nixpkgs {} }: # ... -
Simple expression (not sure what’s the right term here…)
with (import <nixpkgs> {}); mkShell { # declarations }or, to include the explicit-camp:
let pkgs = import <nixpkgs> {}; in pkgs.mkShell { # declarations }
As far as I know, default.nix/shell.nix cannot be given any arguments when used with nix-shell, so declaring them as functions is only a stylistic choice. Indeed, if called with function with head {pkgs}:, the result is
error: cannot auto-call a function that has an argument without a default value ('pkgs')
so it is not like NixOS’ configuration.nix.
Could the function-form be considered an anti-pattern? It threw me off for so long (I may not be alone), and all function heads in default.nix/shell.nix files could be re-written in the non-function form. The latter would also better convey that nix-shell expects a derivation.
For example, the niv example above,
{ sources ? import ./nix/sources.nix
, pkgs ? import sources.nixpkgs {}
}:
would become
let
sources = import ./nix/sources.nix;
pkgs = import sources.nixpkgs {};
in
(Although, I have to admit, the former looks more appealing, at least to me.)
The title of the topic is not the most fortunate but all my previous attempts were at least two lines long so any suggestions are welcome. Thank you!