Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advice regarding alternatives to the with attrset; antipattern doesn't apply in general. #186

Open
nothingnesses opened this issue Oct 4, 2021 · 7 comments

Comments

@nothingnesses
Copy link

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?

@domenkozar
Copy link
Member

pkgs in the example is a nested attribute set, so I'm not sure what do you mean.

Can you provide an example?

@nothingnesses
Copy link
Author

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.

@domenkozar
Copy link
Member

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.

@nothingnesses
Copy link
Author

nothingnesses commented Oct 5, 2021

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?

@domenkozar
Copy link
Member

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?

@nothingnesses
Copy link
Author

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).

@domenkozar
Copy link
Member

Thanks to @r-burns we now have a language proposal to make this simpler: NixOS/rfcs#110

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants