Most active commenters

    ←back to thread

    194 points todsacerdoti | 16 comments | | HN request time: 0.208s | source | bottom
    1. peterldowns ◴[] No.44608614[source]
    Very interesting writeup, as a long-time Nix user I've always been interested in trying guix but never gotten around to it. Great post overall.

    > The thing is, I'm not actually sure if Guix's better documentation helps smooth the onboarding in any way because you have to already know Scheme, which is a more complex language than Nix.

    LMAO absolutely not. Nix-the-language is the worst programming language I've ever had the misfortune to interact with. I picked up Scheme in about 1 day during a class in college. It's night-and-day different.

    replies(3): >>44608725 #>>44608962 #>>44609906 #
    2. otabdeveloper4 ◴[] No.44608725[source]
    > Nix-the-language is the worst programming language I've ever had the misfortune to interact with

    Nix-the-language is just a subset of Javascript with built-in laziness and a slightly different syntax. An absolute bog-standard and mainstream way of thinking about programs in 2025.

    That said, Nix-the-language also suffers from all the same birth defects that manifest themselves in frontend development.

    replies(3): >>44608971 #>>44612433 #>>44617455 #
    3. positron26 ◴[] No.44608962[source]
    > Nix-the-language is the worst programming language I've ever had the misfortune to interact with.

    I feel the same.

    The multi-line strings and string interpolation are both really nice. Unfortunately a lot of the text being munged is bash and usually already ugly, so the result is double-ugly.

    The functional aspects are okay. However, as an expression language and being primarily used in a declarative way, it is frequent to have almost no idea what's going on in Nix. Reading the code and understanding the evaluation are extremely far apart.

    callPackage... It's something I thought would be cool in a language until I actually experienced the depth of disorientation it can cause.

    The remaining syntax has a lot of "but why?" where it just seems to do its own thing relative to other languages, which makes it harder to get into a rhythm.

    Some of the subject matter is the real culprit. The cross compiling sliding window thing... I've studied it several times. If I had to actually do something with it, straight to the LLM. Compilers have targets.

    replies(3): >>44609151 #>>44610822 #>>44612552 #
    4. grep_name ◴[] No.44608971[source]
    > That said, Nix-the-language also suffers from all the same birth defects that manifest themselves in frontend development

    That must be it. The GP's comment really resonated with me, in that learning scheme felt like no task at all whereas I STILL feel uncomfortable with the nix programming language and ecosystem despite using nixOS exclusively on my personal laptop for two years and on my work machine for about half a year now. I've always fumbled over frontend / javascript development though, and avoid it as much as I can at work although I still end up working in it every year or so.

    Nix only won out for me because of the mac compatibility, without which I can't really use it at work

    replies(1): >>44612712 #
    5. xrd ◴[] No.44609906[source]
    I gotta admit, I stopped reading when I saw nix with scheme. If it was scheme plus nix and it was sorted, I might have continued.
    6. sshine ◴[] No.44610822[source]
    > The remaining syntax has a lot of "but why?" where it just seems to do its own thing relative to other languages

    Like what?

    My list of Nix language nits is relatively small, would like to understand.

    One thing that seems under-developed is smart merging. There is // at language level, but then if you want datatype-specific merging, you use functions. That itself is just the power of functional programming. But as it is with untyped languages, you end up doing the same thing slightly different in several places, and a fractal of accidental complexity starts to appear.

    replies(2): >>44611742 #>>44611845 #
    7. chriswarbo ◴[] No.44611742{3}[source]
    > One thing that seems under-developed is smart merging.

    Maybe https://codeberg.org/amjoseph/infuse.nix would be useful? (I find it intriguing, but haven't yet faced a use-case that seemed worth learning it)

    8. positron26 ◴[] No.44611845{3}[source]
    > Like what?

    I've heard people say "JSON with functions", but I think this is much too generous.

    - Functions can be called without delimiters

    - AttrSets have lots of delimiting, very explicit syntax

    - Lists have absolutely no delimiters again

    foo 1 2 is a function call, right?

    So if I need it in a list, I can just write: [ foo 1 2 ] right?

    Note, we pathologically put spaces around lists in Nix because we are subconsciously sure that something is about to bite us.

    [ foo 1 2 ] is a list of three elements, not a function call.

    I forget which terrible thing I was doing, but I had a variation of this syntax trap in my code after naively moving the expression into a list. The error message was, as usual, from the Turtles in Time dimension.

    The mixture of super explicit and implicit delimiting as well as borrowed ideas like \\ and invented ideas like with and import just make Nix feel like it's all over the place, inconsistent, and doing its own thing when we already had a lot of functional languages to work with.

    The evaluation model is completely appropriate for the problem yet pretty unique in programming generally. It has a lot of new ideas that throw even seasoned people well off track. Each new idea is not much, but they compound into not having any idea what we're looking at and watching 50k nixpkgs evaluate just fine while not being able to read any of that code at all.

    I'd prefer something like Haskell, Lisp, or Clojure, but please just one. Using Scheme in Guile is a great choice. It's so much easier to read. Hopefully the macros can be developed to bring the best of lazy evaluation into Scheme and fix the runtime issues.

    replies(2): >>44612245 #>>44613957 #
    9. XorNot ◴[] No.44612245{4}[source]
    Lately I've just been wondering if you couldn't have a python runtime for nix evaluations.

    Ultimately we're taking inputs, making derivations and calling some nix specific library functions.

    It feels like we should be able to do that with a Python library that would have the major advantage of being step debuggable.

    10. fake-name ◴[] No.44612433[source]
    I mean, that's a distinction without a difference.

    I've not written nix, but javascript is a ugly, terrible language. It would make sense that if nix derives from it (whyyyyyy) it would also be terrible.

    replies(1): >>44614105 #
    11. 0x457 ◴[] No.44612552[source]
    So I found some LLMs are wonderful at Nix. A few times I just prompted "port this <github link>" and got a pull request with nix package exactly how I would have written it. One time even manager to implement multiple missing dependencies as well.
    12. 0x457 ◴[] No.44612712{3}[source]
    I think nix-the-language is pretty simple and easy to learn language. It's visually hard to parse and a lot of syntax decisions make you wonder, but it's not the worst.

    The problem is that you're very rarely exposed to it directly. You are always multiple layers of abstractions away from it. Most of these layers are completely undocumented.

    13. sshine ◴[] No.44613957{4}[source]
    Nix function call syntax is completely standard for ML-style functional languages and allows for effortless partial application. The main downside is that error messages can get cryptic, especially so when Nix is untyped.

    Whitespace add list delimiter is not very common, but I have to admit I really like it.

    I was hoping for some “this doesn’t work” kind of things, not “this doesn’t feel familiar”.

    Not sure how Nix doesn’t win the readability contest: literally a config file with function calls, and as little superfluous syntax as possible. I’d say the real criticism is: Nix is hard to write, and nixpkgs idioms (nested, undocumentedabstractions scattered throughout the code) are hard to read.

    replies(1): >>44617402 #
    14. bspammer ◴[] No.44614105{3}[source]
    I disagree with GP, it’s much more like Haskell than JavaScript. Function application is whitespace, functions can only have one argument, everything is an expression, let blocks are the way you define and scope variables. I see very little relation to JavaScript at all, to be honest.
    15. yencabulator ◴[] No.44617402{5}[source]
    > Not sure how Nix doesn’t win the readability contest

    Not sure how you can be serious.

    https://github.com/NixOS/nixpkgs/blob/d600f006643e074c2ef1d7...

          buildGoDir() {
            local d; local cmd;
            cmd="$1"
            d="$2"
            . $TMPDIR/buildFlagsArray
            echo "$d" | grep -q "\(/_\|examples\|Godeps\|testdata\)" && return 0
            [ -n "$excludedPackages" ] && echo "$d" | grep -q "$excludedPackages" && return 0
            local OUT
            if ! OUT="$(go $cmd $buildFlags "''${buildFlagsArray[@]}" -v -p $NIX_BUILD_CORES $d 2>&1)"; then
              if ! echo "$OUT" | grep -qE '(no( buildable| non-test)?|build constraints exclude all) Go (source )?files'; then
                echo "$OUT" >&2
                return 1
              fi
            fi
            if [ -n "$OUT" ]; then
              echo "$OUT" >&2
            fi
            return 0
          }
    
    (Do note the Nix escaping on top of the shell horrors.)

    Nix just comes from a culture of utter utter horrible code. It's my daily driver, but I am holding my nose.

    https://github.com/NixOS/nix/blob/94ec9e47030c2a7280503d338f...

            std::string rc = fmt(
                    R"(_nix_shell_clean_tmpdir() { rm -rf %1%; }; )"s +
                    (keepTmp ?
                        "trap _nix_shell_clean_tmpdir EXIT; "
                        "exitHooks+=(_nix_shell_clean_tmpdir); "
                        "failureHooks+=(_nix_shell_clean_tmpdir); ":
                        "_nix_shell_clean_tmpdir; ") +
                    (pure ? "" : "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;") +
                    "%2%"
                    "dontAddDisableDepTrack=1;\n"
                    + structuredAttrsRC +
                    "\n[ -e $stdenv/setup ] && source $stdenv/setup; "
                    "%3%"
                    "PATH=%4%:\"$PATH\"; "
                    "SHELL=%5%; "
                    "set +e; "
                    R"s([ -n "$PS1" -a -z "$NIX_SHELL_PRESERVE_PROMPT" ] && PS1='\n\[\033[1;32m\][nix-shell:\w]\$\[\033[0m\] '; )s"
                    "if [ \"$(type -t runHook)\" = function ]; then runHook shellHook; fi; "
                    "unset NIX_ENFORCE_PURITY; "
                    "shopt -u nullglob; "
                    "unset TZ; %6%"
                    "shopt -s execfail;"
                    "%7%",
                    shellEscape(tmpDir),
                    (pure ? "" : "p=$PATH; "),
                    (pure ? "" : "PATH=$PATH:$p; unset p; "),
                    shellEscape(dirOf(*shell)),
                    shellEscape(*shell),
                    (getenv("TZ") ? (string("export TZ=") + shellEscape(getenv("TZ")) + "; ") : ""),
                    envCommand);
    16. yencabulator ◴[] No.44617455[source]
    Yes, clearly every general-purpose language like Javascript has specialized the string type for the business domain of text-templating for bash scripts.

    For example: https://shealevy.com/blog/2018/08/05/understanding-nixs-stri...