A review of Nix/NixOS after using it on all my machines for three years. I'll cover what works, what doesn't, and why it's the first OS that's stuck with me.
Let me disagree there, the language is trivial. It’s just JSON-lookalike with expressions, with a lot of nice touches that make using it much easier than all the alternatives (e.g. sane multi-line string handling, lazy evaluation, default values, powerful key/value sets, etc.). The only real stumbling for me when first encountering it was realizing that functions can only take a single argument (which can be a key/value set) and that functions are literally just : (e.g. (a: a + 5) 6 => 11). That’s easily missed if you just look at a file without reading the documentation.
The thing that makes it hard is just the complexity of the actual package collection, your configuration contains literally your whole system, and it’s not always obvious where to find the thing you need, since sometimes it’s a plain package, sometimes it is a services.foobar.enable = true and sometimes you have to fiddle with override or other package specific things. Knowing that
https://search.nixos.org/ exists is half the battle here.
There is also the lack of static typing that can lead to rather verbose error messages, but it’s not like many other configuration formats have that either.
There are a few gnarly things about Nix, even for someone who’s familiar with Haskell (the most similar language to Nix that’s even close to mainstream).
Dynamic typing (you mention this briefly). Some people like the extra flexibility that dynamic typing gives, but there’s a tradeoff: more errors. The thing is, due to NixOS’s complicated structure, the traceback for an evaluation error might not give you any information about where the cause is (indeed, the traceback might not include a single line of your own code!). This makes errors unusually costly in NixOS specifically, so any language feature that causes more runtime errors automatically has a worse impact than it would in a more “normal” language.
The “standard library” (builtins) is extremely sparse. You basically have to depend on at least nixpkgs-lib if you want to get any real work done.
No real data abstraction mechanisms. No ADTs, no nominal types. The only composite types are attrsets and lists. The usual way to encode a custom type is as an attrset with a _type field or some such.
While we’re at it, very limited pattern-matching.
Clunky list literal syntax: no commas between list elements. I can’t tell you the number of times I’ve forgotten to surround list elements in parentheses.
Can anyone remember the rules for escaping ${ or ''? I have to look them up every time.
Let me disagree there, the language is trivial. It’s just JSON-lookalike with expressions, with a lot of nice touches that make using it much easier than all the alternatives (e.g. sane multi-line string handling, lazy evaluation, default values, powerful key/value sets, etc.). The only real stumbling for me when first encountering it was realizing that functions can only take a single argument (which can be a key/value set) and that functions are literally just
:
(e.g. (a: a + 5) 6 => 11). That’s easily missed if you just look at a file without reading the documentation.The thing that makes it hard is just the complexity of the actual package collection, your configuration contains literally your whole system, and it’s not always obvious where to find the thing you need, since sometimes it’s a plain package, sometimes it is a
services.foobar.enable = true
and sometimes you have to fiddle with override or other package specific things. Knowing that https://search.nixos.org/ exists is half the battle here.There is also the lack of static typing that can lead to rather verbose error messages, but it’s not like many other configuration formats have that either.
Using a language server like nixd also helps a lot with auto completing packages and options in your config.
Apparently people are also working on the nickel configuration language to address some of the nix limitations and difficulties.
There are a few gnarly things about Nix, even for someone who’s familiar with Haskell (the most similar language to Nix that’s even close to mainstream).
builtins
) is extremely sparse. You basically have to depend on at leastnixpkgs-lib
if you want to get any real work done._type
field or some such.${
or''
? I have to look them up every time.