This is a pattern I've seen over and over: if a project tries to do something different, the novel aspect gets blamed for issues that would not be surprising in any other context. When faced with a massive awful codebase in Java, well, sometimes legacy code can be a pain, right? It is what it is. People rarely jump to "OOP is a mistake" or "Java is completely unusable". But that's exactly what happens all the time with, say, functional programming.
Pointing to an uncommon choice as the underlying cause of a problem makes for a nice, pat story; the pervasive, diffuse problems inherent to messy legacy code do not. After all, here's a single thing that, presumably we can actually change! Nix being functional is an objective fact while people can—reasonably or not—disagree on how well-designed and well-written Nixpkgs-the-codebase is. Besides, even if we could agree, what could we do about it? We all know how much momentum legacy code has and how hard it is to make anything beyond local improvements. Being a socially convenient story doesn't mean it's a particularly strong explanation, but it does mean that people will believe it even if it isn't.
Nix pills, the official manual, etc. aren't really there yet--they talk about all kinds of paradigms that might (?) be going away like nix-env and its ilk. It's just extremely painful to track down the current best practice and way to do things in nix--you're bouncing off all kinds of docs and finding multiple conflicting or out of date ways to do things. Someone needs to give folks a slim book about nix flakes and the flakes way of doing things, the nix language, and a tour of nixpkgs, and IMHO there will be a lot more people using it.
If it was bad why show it to me at all?
So to most programmers, imperative code is easy and FP is hard, but on an objective basis both can be simple. In a way FP may be simpler (according to the talk), as e.g. mutable variables complect/mix together values and time.
The biggest barrier, as I see it, is not actually Nix or Nixpkgs code, but the way NixOS differs from every other Linux distro. Most of my delving into Nixpkgs has been motivated by getting something working that would be trivial in a traditional distro. I agree the Nix language is a red herring, what's really needed is to make work other than "adding a package to Nixpkgs" easier. Actually usable introspection tools that the GP mentioned would be great.
The same thing we do for other paradigms (system architecture, programming concepts, etc.) - find and document common patterns, then find ways to transition to the patterns away from things out of pattern, and lastly introduce automatic refactorings that do fix these things in bulk.
I definitely agree with you on the evolution thing. Homebrew is a similar DSL for installing packages on macOS. It has the problem where things get deprecated from the DSLs (Casks and Formulae) which leads to not being able to run various commands until previously installed software is fixed.
I'd just like to take a moment to reiterate that object-oriented programming is a mistake produced by cargo-culting half a dozen different styles used by competent programmers (including the devolpers of smalltalk and its relatives, from which OOP appropiated its name), and that Java is completely unusable by anyone with a sense of self-respect and a awareness that programming languages can be better than least-common-denominator noe-COBOLs. I'm not familiar with the specific codebase you're refering, but it would probably be at least less massive and less awful if it had been written in a more decent language, like Haskell or C.
Java is a tiny language with not too many concepts going around sitting on top one of the best runtimes with one of the biggest ecosystems. It is a very sane and good choice for almost every program out there, especially that empirically we have absolutely zero evidence for any significant difference between language productivities, other than managed languages being a boost (so your mention of C, which is arguably a language with so many faults one could fill a whole book about, is frankly, quite laughable).
I'd love to hear from someone deeply familiar with Nix and Guix about laziness.
I'm deeply familiar with Nix and I've concluded that lazy semantics is absolutely critical for a configuration language. It lets me refer to other attributes of my configuration from anywhere. For example, I can refer to port number from my whatever service in my firewall. Nix's system of overlays depends on laziness too to provide efficient late-binding familiar from OOP.
I don't need to topologically sort the evaluation of the various inter-dependencies of my configuration. So long as there exists an evaluation order, laziness finds it.
Laziness is compelling enough that I managed to convince the author of Jsonnet <https://jsonnet.org/> of it when he was designing it, and in turn he helped me design what is now known as overlays in Nix.
I don't even understand how Guix manages to work without laziness, though clearly it does somehow. I'm curious as to how that is possible, though I fear I will only ever truly understand by diving into Guix.
As an OOPer, inheritance is one of the things that is generally trotted out as the worst aspect of OO languages. This leads to the mantra "favor composition over inheritance". Much has been written about why and how. But it seems to cause the same pain points that people talk about with respect to laziness in Nix. "Spooky action at a distance" is one of my favorite ways of describing some of these problems.
(I'm not super familiar with Nix, so I could be misreading the points about laziness. Please forgive me if so.)
I certainly think people should exercise caution as this could probably be abused quite badly. Maybe people will come up with better designs in the future. However I will say, that the method it has replaced was much worse. The old way was adhoc and almost always failed to achieve ones desires in all but the simplest cases.
Don't just take my word for it. Peter Simons also agrees: <https://github.com/NixOS/nixpkgs/commit/3c8b33eee442fd573d47...>
That’s not a property of laziness but of how Nix evaluates configurations. I think people overvalue what laziness brings them because they attribute to it things which could be done equally well with an eager language.
Being able to write
let usercfg = { username = "nix-user";
homedir = "/home/" + usercfg.username;
};
in usercfg
is nearly a hallmark of non-strict semantics, which is achieved by lazy evaluation.Strict languages can simulate these non-strict semantics by using functions of no parameters to delay evaluation, but you lose the efficiency that comes from the memoization of record fields that you get with lazy evaluation.
P.S. The above would perhaps be more likely be written as
rec { username = "nix-user"; homedir = "/home/" + username; }
but when specifying larger configurations composed of multiple nested records with wide cross-cutting inter-dependencies, "rec" doesn't really cut it as "rec" works best with extremely local inter-dependencies.There's a case to be made about improving the state of the Nixpkgs APIs though. Stabilizing the APIs and documenting it more thoroughly would dramatically change how people perceive the complexity of Nix. Experienced Nix users grep the Nixpkgs repo to learn about its APIs, but that's far from ideal for newcomers who won't even know where they should look for information.
Still, despite its reputation, Nix lowers the bar for software packaging. Package definitions tend to be more concise, customizable, and reusable than the competition. Nixpkgs contains many useful utilities for packaging and there's an abundance of real world examples contained in a single repo. I also frequently work with RPM, but Nix is much easier in comparison.
When documented examples began steering me towards the still experimental nix flakes and using the sorts of with ever more flags required commands, I bailed and built it using salt. I want to like nix but the current state of things was a massive put off.
There's a push to make them not be experimental anymore since so much of the community including myself is using them.
If I’m learning something as big as nix with all the facets it has, I don’t also have time to learn it’s entire community history. It’s not a good thing that I need to do that in order to make a decision about how much to trust experimental features of a tool when I’ve not even been using it more than a few hours from the moment of downloading the iso and installing it. It’s a put off to someone new coming to use nix for the first time.
Yup. I can't even imagine what could I accomplish if I'd have something like a "python library" for nixpkgs. I still use nixos but gave up fiddling with nix for a while, after trying to wrap some stuff I am using/developing.*
* (Yes, I know it's easy. I just need flakes or correct amount of "lib: prev: { self"s. Sadly not for me.)
The majority of communication I've seen from Nix maintainers over the last few months has been about exactly this.
The submitted post is about exactly that while Nix powerful, they want more people to be able to use it without having to pay a steep penalty to learn it.
Nah. The logical conclusion of this is that Nix should be some Java-like, Python-like, or whatever else qualifies as something that the average developer knows.
Nix needs to be declarative which rules out the average PL paradigm.
> […] , but can the next iteration provide an on-ramp which doesn't involve learning a new lang and paradigm? Guix folks sure think so.
Does the average developer know Scheme? I think you just played yourself.
I think most of the docs problems could be solved with the meta-strategy of “deeply understand all the things the Rust ecosystem got right with docs, discovery, and general pedagogical structure, and replicate that”. Actually have a canonical set of docs. Link liberally between packafes and stdlib. Figure out typing so you can get those hints and links in your IDE. Fix the package docs so they actually tell you what functions the packages export, instead of relying on the wiki for instructions. Etc.
Basically, pay a couple excellent docs people for a few years.
I found the language a bit weird but not terrible to learn. But if it’s possible to build some porcelain for common usecases that skips there need to grok the language, that could be quite transformative. I do wonder if the “dev env/packaging” use-case might be simpler than the “run and configure a whole OS” usecase.
I think every project would love having the money to hire someone full time to work on the documentation and evangelism.
Learning to use a lazy functional programming language remains relatively easy - we use to teach the basis in Ocaml in three hours when I was a student - and Git shows people can tolerate awful CLI tool UX.
I think your point 3 is where most of people issues with Nix lie except I wouldn’t limit myself at a lack of practical enough documentation. Nix documentation pretty much just doesn’t exist period.
If you want to use Nix, you will have to go through the packages or the implementation to understand what’s happening. That’s not very welcoming especially when you consider that’s the other Linux distributions which tried to do things differently in the past and could be a source of users for Nix OS, first of them Gentoo, have absolutely stellar documentation.
It's the easiest programming language in the world.
(Which is a problem when people start building huge projects like nixpkgs with it. It's not a language fit for programming-in-the-large, just like Javascript isn't.)
nix flake show templates
But the examples in there are a bit out of date and don't necessarily reflect real world usage and are lacking in comments (e.g. still using defaultPackage, not using flake-utils, etc.).I've only had to add a few lines to my configuration over 10 PCs and laptops.
I have trouble understanding your question. Why do you want to use Nix if you use a system which comes pre-configured to do something else?
1. Approachability for those not indoctrinated in lazy, declarative, functional programming (i.e. Haskell); nope, Nix Pills are not sufficient for the average dev
2. Editor tooling to help guide the writing of expressions (just as anyone learning C# or Rust can use LSP); a better type system for Nix would help here
3. Better documentation for practical things like "Using Nix to manage the dependencies and package a C++ program using Meson", rather than having people piece this together from a bunch of disparate docs
4. A much better CLI UX than `nix-env -qa` and the like (this is ongoing and experimental, but even that broke recently, causing lots of confusion; now it requires `nix --extra-experimental-features nix-command --extra-experimental-features flakes search nixpkgs`)
5. To seriously answer the question: is the Nix language required for the Nix packaging system to exist? Laziness is required, to some degree, but can the next iteration provide an on-ramp which doesn't involve learning a new lang and paradigm? Guix folks sure think so.
I feel like Nix folks have been focused so long on solving the tough problems of declarative, deterministic packaging that they haven't been able to focus on the UX. I also feel like folks for whom Haskell is comfortable may not realize just how absurd it feels to everyone else. Perhaps like the early days of Git.
I do really hope Nix succeeds in this, though; I've been using it, or it's been using me, for several years. [1] and [2] for more info.
[1]: https://blog.jeaye.com/2015/11/24/nixos/
[2]: https://blog.jeaye.com/2017/07/30/nixos-revisited/