I spotted this exchange on Matrix earlier and it reminded me of a suspicion I’ve had that one of the hurdles to learning Nix has to do with its weird relationship to fundamental concepts like what it means to “install” software:
Hi there. New to Nix here. I don’t get how to add extends to php, i installed php74 and php74Extensions.redis, but the redis extension doesn’t seem available.
Off the top of my head, I can come up with 3 that feel precise.
(Terms like build and install are common, but overloaded with enough meaning that I wouldn’t call them precise? Even if we use them to mean something idiomatically precise, misinterpretations will abound.)
My list so far:
instantiate: IIUC this means to evaluate a Nix expression that produces a derivation and write the serialized .drv out to the store.
substitute: IIUC this means to download a realized artifact and place it in the store. (This is listed in the Glossary - Nix Reference Manual but the definition isn’t very approachable.)
realise/realize: IIUC it means ~substitute-or-build, so it’s probably the “precise” alternative to “build” in many contexts. That said, the documentation (which is a little scant) mostly uses the noun form (realisation/realization), as in: nix-store - Nix Reference Manual
I’m not sure if the new Nix command/UX effort provides newer terms for these (I’m still mainly using the old commands).
I am not aware of any more precise term than install that means “make software available to use”. But, even though Nix allows different modes of installation than the traditional imperative one (e.g. declarative build & environment switch, and (transient) declarative shell), I think that is still close enough to not be a problem.
The main issue, in my opinion, stems from the fact that all packages are born equal from the perspective of stdenv.mkDerivation and buildEnv, even though passing the packages to those low-level construct might not result in a proper installation. That is done either intentionally (e.g. not linking development files to buildEnv by default) or through technical limitations (like PHP extensions needing to be enabled in PHP configuration file).
We could emulate what FHS allows by having interpreters pick up ecosystem packages from buildInputs/paths – for example, Python does this within stdenv.mkDerivation using a setup hook – though that feels too imprecise and magic to me.
Alternately, we could add passthru.nonStandalonePackage = "php.extensions.${pname} can only be installed through `php.withExtensions`. See <manual-link> for more info." and have buildEnv and stdenv.mkDerivation check for that.
Though it would be a lot of work to add it to every C library to cover the most common issue (people trying to install C libraries using a global method). And even if we did that, some libraries also contain tools so we would need to distinguish between the uses somehow. (We could require using bin output explicitly to avoid the warning, but it would be a very annoying BC break.)
I honestly think that from a user’s perspective it’s always easier to use familiar terms for the most common operations in the CLI even if they don’t have the same exact meaning that they have in other systems.
And from a new user’s perspective interaction with Nix is already right off the bat overloaded with lots of alien/unfamiliar terminology that obviously makes sense if one works with it for years, but feels quite intimidating for a new user: derivation, expression, options, etc. All these terms correspond to familiar words that have very unfamiliar meaning in this alien Nix world and were probably chosen exactly due to reasons you’ve outlined: to avoid collisions with existing terms because they don’t match exactly.
Another recent development where this “precision terminology” really backfired is the term “flake”: unless the user knows exactly what they’re searching for, there’s currently no way to discover that such concept even exists and that it actually might be a solution to a problem they’re facing.
In my opinion, this unnecessarily raises the entry bar and nukes discoverability. Instead, I’d have preferred if more general/overloaded terms were used more widely for the most common operations, but there was a precise glossary of what those terms mean exactly in nix world.
It is perfectly fine, however, to have precise but unusual terms used for deeper concepts that the user does not have to routinely deal with.
There is a thing in the CLI that maps quite literally to the word install, and yet I think there’s fairly broad agreement that imperatively installing things with nix-env is a tarpit for new users. What do new users need to guess to find an approach successful users would recommend?
I don’t think this has much to do with the “precision terminology” and has everything to do with flakes still being an experimental feature. If/when flakes become canonical, the term will be unavoidable.
There is a thing in the CLI that maps quite literally to the word install, and yet I think there’s fairly broad agreement that imperatively installing things with nix-env is a tarpit for new users.
I agree. And I think the solution would be to change the tutorials that start with “Keep in mind, that the intended way to manage your NixOS system is by managing it declaratively a link. However, there’s a also an alternative way to install packages into your current environment that can be useful in a situation like this or that.”
Because if you were to change the word “install declaratively” to something else like “emplace”, then people will 100% not search for it ever and they’ll definitely find only the nix-env way of installing things imperatively. So if you use word “install” software in a declarative way, even though it’s technically incorrect, people will be able to at least find it.
And it is in fact a problem that for a term as common as “installation” the first search result in nix is a sub-optimal way to achieve what the user probably implied. So instead of further obfuscating the intended way, I’d argue it’s better to use a more obscure term for nix-env installing things (the more niche way). Call them “imperative install” or something that looks more suspicious to a newcomer.
I’m not sure we need new terms (that’s why I posed this as a question), but I also feel like this is a bit of a strawman of what having a specific word entails. It imagines you’d just start using the word without clarifying what you mean. It should be obvious that the same solution in your first paragraph applies just as readily to using a different word as it does to using install with an adjective.
Yes, it raises the bar on knowing what to search. Obviously, speciating the terms means explaining them clearly somewhere, and leaving more breadcrumbs. But it also means that, once you learn what to search, you can actually find people actually talking about the approach you’re trying to learn about. As opposed to always having to wade through rafts of results about other approaches.
This is, I think, the problem people are gesturing at when they say learning Nix is hard and the documentation needs work (despite there being mountains of documentation). There are tons of valid ways to do things, and it’s very hard for new users to figure out which syntax, patterns, and recommendations apply to their current goals until they crest the third plateau or so.
‘Integrate’ might be a useful verb for withPackages-like constructions. In other paradigms, installing packages typically makes them available not only to the user, but also to each other. With Nix, the goal of installation is (typically) only to make them available to the user.
Idk if there’s a verb which connotes preparing a range of things for separate usage, which is mostly what one does when they use nix profile install, nix-env -i, or environment.systemPackages.
Anyway the idea of a distinction between preparing programs for the user’s use vs. for use by one another seems like it could go a long way.
Documentation summarizing all of the deliberate impurities in Nixpkgs and how they work might likewise go a long way toward helping new users understand when to expect installed programs to be isolated from one another and when not!