nix.dev
nix.dev copied to clipboard
Advice regarding alternatives to the `with attrset;` antipattern doesn't apply in general.
The advice in this section doesn't apply if the list elements are nested attribute sets (i.e., they have dots) or are function applications (i.e., they are surrounded by parentheses). Maybe other alternatives in these cases should also be provided?
pkgs in the example is a nested attribute set, so I'm not sure what do you mean.
Can you provide an example?
Sure thing. So here's a part of the "home.nix" configuration I use for Home Manager, which builds fine:
{ config, pkgs, ... }:
let
inherit (builtins)
fetchGit;
in
{
home = {
homeDirectory = "/home/a";
packages = with pkgs; [
(nix_gl alacritty)
rust-bin.stable.latest.default
];
stateVersion = "21.11";
username = "a";
};
nixpkgs = {
overlays = [
(self: super: {
nix_gl_go = (import (fetchGit {
ref = "main";
url = "https://github.com/guibou/nixGL.git";
}) {}).nixGLIntel;
nix_gl = program: pkgs.writeShellScriptBin program.pname ''
${self.nix_gl_go}/bin/nixGLIntel ${program}/bin/${program.pname} "$@"
'';
})
(import (fetchGit {
ref = "master";
url = "https://github.com/oxalica/rust-overlay.git";
}))
];
};
targets.genericLinux.enable = true;
}
But it doesn't work if I try to apply the pattern from the website:
{ config, pkgs, ... }:
let
inherit (builtins)
attrValues
fetchGit;
in
{
home = {
homeDirectory = "/home/a";
packages = attrValues {
inherit (pkgs)
(nix_gl alacritty)
rust-bin.stable.latest.default;
};
stateVersion = "21.11";
username = "a";
};
nixpkgs = {
overlays = [
(self: super: {
nix_gl_go = (import (fetchGit {
ref = "main";
url = "https://github.com/guibou/nixGL.git";
}) {}).nixGLIntel;
nix_gl = program: pkgs.writeShellScriptBin program.pname ''
${self.nix_gl_go}/bin/nixGLIntel ${program}/bin/${program.pname} "$@"
'';
})
(import (fetchGit {
ref = "master";
url = "https://github.com/oxalica/rust-overlay.git";
}))
];
};
targets.genericLinux.enable = true;
}
Hopefully that shows what I mean clearly. That said, I'm pretty new to Nix, so it's just as likely that I'm not doing things properly. In that case, please do let me know the proper way so I can improve.
Thanks!
Indeed for referencing nested attributes the example doesn't work. Same for functions!
In that case it's best to refer to pkgs.rust-bin and pkgs.nix_gl.
What if the section included advice about using the concatLists builtin to allow the problematic attribute sets to be included using the longhand form, whilst still allowing the original advice about the shorthand form to be used when applicable? So the result will be something like:
{ config, pkgs, ... }:
let
inherit (builtins)
attrValues
concatLists
fetchGit;
in
{
home = {
homeDirectory = "/home/a";
packages = concatLists [
(attrValues {
inherit (pkgs)
bc
gcc
gdb
ripgrep;
})
[
(pkgs.nix_gl pkgs.alacritty)
pkgs.rust-bin.stable.latest.default
]
];
stateVersion = "21.11";
username = "a";
};
nixpkgs = {
overlays = [
(self: super: {
nix_gl_go = (import (fetchGit {
ref = "main";
url = "https://github.com/guibou/nixGL.git";
}) {}).nixGLIntel;
nix_gl = program: pkgs.writeShellScriptBin program.pname ''
${self.nix_gl_go}/bin/nixGLIntel ${program}/bin/${program.pname} "$@"
'';
})
(import (fetchGit {
ref = "master";
url = "https://github.com/oxalica/rust-overlay.git";
}))
];
};
targets.genericLinux.enable = true;
}
I'm not sure if there's a more concise way to do this than using concatLists, and if so, maybe that could be used instead?
I wonder if the complexity of reading the code of figuring out concatLists and attrValues is really worth typing out pkgs 3 times more than it is currently?
The value of doing this would likely depend on how many elements the list has. I only included a few in the example above but my actual configuration has more than a dozen elements, so in my case I think it is justified, but in cases of small lists, this wouldn't be worth doing. In any case, I think it's still worth including this advice (or any other similar, simpler solution, if it exists) because the current advice in the website doesn't apply to all cases as mentioned previously. Readers can just decide for themselves if they think it's worth doing depending on their situation (i.e., they might decide to use it if their lists are large enough).
Thanks to @r-burns we now have a language proposal to make this simpler: https://github.com/NixOS/rfcs/pull/110