Nix is lightweight, pure and maximally lazy. It's a simple DSL that evaluates targets -> derivations (build specs.) Considering it can build an entire OS with so few features, I'm not sure adding a numeric tower and Turing-completeness is really desirable.
Also, I'm surprised this article doesn't mention Hydra. Reproducible binary caches and automatic testing are one of the key advantages of these systems -- does Guix use it?
I'd like to emphasize more on how much Nix and Guix share and that for the better part Guix should be thankful to Nix!
With regard to Mozilla, Rust might precisely _not_ be such a mistake, but you are right, I should praise Mozilla for moving on then (although I know nothing about Rust, so I can only guess here).
> I'm not sure adding a numeric tower and Turing-completeness is really desirable.
That's what I meant: Turing-completeness comes for free, it does not harm the project and you'll need it sooner or later. Even if the devs don't need Turing-completeness, not adding it to a project is effectively limitating what the user can do with a program.
I fell for it myself and at the time, I had the feeling that "a Turing-complete language might be too much for the project." Today, I believe that this thought is mostly an ungrounded gut-feeling.
> Hydra
Thanks for pointing it out, you are right I should have mentioned it when I wrote about the continuous integration. Will do.
Guix itself uses Hydra on the old server and Cuirass (a Scheme-based CI system :p) for the new one.
And to be fair, so many bad DSL has been done in the past, espacially behind corporate walls, that I understand the avortion for them. And anyone who had to work on a Lisp or Ruby code created by a DSL inspired hacker know the pain.
DSL have many problems, but the most obvious one is that you get a language without the testing, documentation, tooling and community of a battle tested general one. And because by nature it targets a niche, the miracle needed for it to get real traction requires even bigger divine interventions.
Even if nix was amazing (I couldn't tell, I haven't tried it), and the resulting product, not only fantastic, but worth people switching to it (which is not the same and harder to achieve, or even to recognize with honesty), the scale it would need to become practical may not even fit in the niche it targets.
Um. Rust is not a DSL; if XUL failed and Rust succeeded, then that's (weak) evidence in favor of "DSLs suck".
Being able to run `nix-shell -p` and get a shell with a program installed is super cool. Also, being able to add a package to the system declaratively is super cool. However, one thing I wonder about is workflows.
For example, I have a lot of Jetbrains IDEs installed for various languages, but I don't want to pollute my global environment with tools, especially command line tools that pollute the PATH. Let's say I want to use Jetbrains Rider. I can easily start a shell with the dotnet SDK with `nix-shell -p dotnet`, then start Rider under that shell. This is OK, but it feels wrong to me. It feels weird that launching Rider outside of nix-shell won't ever work, yet it's installed globally. And yet, I also kind of want it to be globally installed...
Another solution would be to have Nix expressions for every project I work on. This actually seems better and I've adopted it for a couple projects, but it also irks me because it feels half-baked. I don't know where to put these expressions other than next to the project, but I don't think it belongs in version control. Also, I'm very mixed for what belongs in these environments. Should it be personally suited, with my IDE and developer tools? If I do that, I can't share the same code I'd use for my tooling as I would for my Nixpkg (assuming there is a nixpkg) which leads to a divergence I don't like. (Though maybe that can be solved?)
I almost want a robust system of working environments that encapsulates this. So, I could think about my Nix workflows as separate environments. Declarative or imperative, and ideally with more encapsulation than a typical nix-shell. Maybe instead of orienting my workflow around opening an IDE and opening a project, I can orient it around opening a project environment and then opening an IDE inside of it.
At this point I'm just rambling. I still prefer NixOS for practical reasons, since it makes my complex IOMMU setup a cinch and keeps all of the configuration for it surfaced and documented. But dang, the potential here to shift workflow paradigms is enormous, it feels.
Hah, me too. :)
> I really love NixOS, but I'm at best lukewarm on Nix as a language.
My biggest issue as of now is that the documentation focuses on which individual files you need to touch, but doesn't really explain the big picture. For example, /etc/nixos/configuration.nix contains a function that takes { config, pkgs, ... }. Where do these come from? Where can I find documentation for them? What is in the ellipsis? More generally, where can I find a high-level overview of how the different components interact with each other during, for instance, nixos-rebuild?
What about using .gitIgnore or using a git submodule for them? Ideally you could have one central repo for nix workflows, and then just have git submodule point to the repo's subfolder, so when you do submodule init, it pulls down that specific folder. Otherwise, you could use .gitignore and a symlink to that as you might do with your dotfiles if you manage those through version control.
I'm not familiar with Jetbrains or dotnet, but you could probably use makeWrapper to make a "jetbrains-with-dotnet" package, something like this:
with import <nixpkgs> {};
runCommand "jetbrains-with-dotnet"
{
inherit dotnet jetbrains;
buildInputs = [ makeWrapper ];
}
''
mkdir "$out/bin"
makeWrapper "$jetbrains/bin/jetbrains" "$out/bin/jetbrains-with-dotnet" --prefix PATH : "$dotnet/bin"
''
This package provides a `jetbrains-with-dotnet` script, which adds the `bin` directory of the `dotnet` package to the start of $PATH then runs the `jetbrains` executable from the `jetbrains` package.Installing such a package globally will put the `jetbrains-with-dotnet` script in your PATH, but it won't pollute your system with anything from dotnet or jetbrains: those will be downloaded/built and cached in the Nix store, but are only accessible via that script.
I use nix-buffer[0], which lets Emacs pick up the environment automatically when I open any file in the project. And as long as you only use setq-local it'll stay scoped to those files, "normal" files still open in the regular user environment. It's even seamless to keep files from multiple such projects open at once.
What do you mean it won't work? I think rider will launch without dotnet, If not then rider dependencies should be fixed to include dotnet. Otherwise, it's the same case for any other distro.
> but I don't think it belongs in version control.
Why not? In fact you should put them in vc since anyone with nix can easily build the program exactly same as on your machine.
> Should it be personally suited, with my IDE and developer tools?
You can create different nix files: e.g. in ide/default.nix you can inherit your default shell.nix and put extra dependency. You may want to skip checking this in vc though.
For a good organization of nix files look at the reflex-frp haskell project.
The specific reason is Ruby + RoR leading to nokogiri... which is something people have been dealing with for several years and there's no solution, and I lost the one file where I managed to get it working good enough to launch rubymine in a way that sees everything necessary.
Similar issues crop in other places, due to how Nix dependencies are handled like unflattened node_modules at times :/
And while I think Nix language is kind of strange, there is at least one reason I prefer it instead of a Lisp (this being a person that uses Clojure everyday at work): no parenthesis.
It is not that I think Lisp is a bad language because of the parenthesis: I love the consistency and simplicity of the language. However, Lisp is one of the few languages that I don't feel productive at all without a proper editor setup (rainbow parenthesis, slurp, barf, etc.) and I think this is bad for configuration files since sometimes you simply don't have the proper setup.
I can easily edit /etc/nixos/configuration.nix in NixOS using only vi to bootstrap my system. I don't think it would be as easy to do the same using GuixSD.
[1]: https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c5...
operating-system:
...
packages:
- vim
- %base-packages
instead of: (operating-system
...
(packages (cons* vim %base-packages)))
would that help you? No more parenthesis, the complexity of cons* is hidden behind the "-" and it's pretty trivial to convert between one syntax and the other. If it was possible, how would that affect your opinion on guix? What if the installer came with a pre-configured vim for scheme?btw, I'm also a guix and a vim user, and I don't use anything special for parenthesis. I just close them manually like a grown-up (which is a very usefull skill to have when you want to impress an emacs user :p).
tl;dr s-expressions are (by design) trivial to both parse and generate, and there are already a bunch of tools to convert to/from a other formats (such as indented text). There's no need to create/use a whole different language+toolchain+ecosystem just to avoid parentheses.
I prefer to think that Nix "out-schemes" scheme.
To be fair I have seen/heard lots praise it a lot for delivering stability to the servers they manage, but in this day and age, I'm not sure it's even worth trying to learn something to manage servers when the cattle approach is so much better (just shoot it). Even when stateful applications get involved, distributed storage is springing up to make it easier than ever to take down a server but have the data it had still be accessible, granted it was replicated, and sync if/when the machine ever comes back up. If the world evolves in that direction, it seems like people will only care about packages at VM/container/whatever base layer build time.
Don't want to be the downer here but I don't think it's likely that Guix is going to cross the usability chasm. I've invested a lot of time/interest/effort in projects that were better, but never crossed the usability/mindshare chasm and while I hope I'm wrong, this feels like some of the other ones.
Completely unrelated to that though, this quote rang true to me:
> Guix is a fork of Nix and addresses the main issue that Nix didn’t get right: instead of comming up with a homebrewed domain-specific language (DSL) with its own set of limitations and idiosyncrasies, Guix uses a full-fledged programming language. (And a good one at that, since it’s Guile Scheme, a Lisp-based language.)
I think Hashicorp has this problem with HCL (see the recent updates[0] announced at the last HashiConf, the `for` keyword is now in HCL) -- though I'm not recommending they fix the problem with lisp, people need to stop making DSLs then bridging the gap between their DSL and a full programming language. I much prefer the Pulumi[1]'s approach -- though it leaves devs lots of rope to hang themselves with ("recursive infrastructure building functions...why not?").
[0]: https://www.hashicorp.com/resources/keynote-terraform-free-s...
Git was self-hosting from day 3, but consisted only of a few pieces of exposed plumbing. As more porcelain was bolted on, it got to the point where flashy UIs could exist. Porcelain isn't all trivial either - consider "git rebase"!
NixOS today is like early Git.. usable and powerful, but not user-friendly. It needs a good UI, a graphical installer, and high-level porcelain to hide the plumbing unless you need to drop into it.
As for the cattle question, I think Nix's real power will come from efficient, declarative "Dockerfiles" and serving as a Bazel-like build system. There was a project for this, Hocker, but it seems inactive.
I'm not sure even that's enough, Nix is trying to win the lottery 3 times -- pushing a (essentially universal) package manager, a programming language, and linux distribution into the mainstream at the same time. What you noted might solve package management, but I'm convinced no one actually knows just how to make programming languages/OSes popular enough to hit and stay in the mainstream, outside of lots of money for marketing or serendipity.
All this said... Nix (OS + package manager) is definitely on my list of things to take for a spin -- I watch and read stuff about it but haven't taken the plunge just yet. It's very popular in the Haskell Ecosystem [0].
Nixpkgs' dockerTools.buildLayeredImage can build Docker images from your Nix packages.
There's also pullImage and buildImage which combine to let you use regular Docker base images, but frankly that seems pretty pointless.
That said, NixPkg (the package manager) is incredibly powerful, because it can build containers more quickly than Dockerfiles [1] or other specifications -- and it can do so in an entirely reproducible manner, with efficient caches for CI servers and developers. This becomes particularly powerful if your team works in a compiled language with long build times, like C++, or if your team works with a variety of languages. Particularly in scientific computing, it's not uncommon to have a lot of Python {2,3} with C/C++ dependencies, and perhaps a cmdline utility in another language or two. At this point something like 'pip install' no longer really cuts it, and NixPkg can step in to produce app images and development/CI environments in a snap. These images can then be backed into your favorite container runtime with the confidence that you could rebuild the entire container with a 1-line patch and actually have the same contents everywhere, and the new 'nix path-info' and 'nix log' commands can give you deep introspection into the binaries: showing the full transitive closure of build-time or runtime dependencies, their sizes on disk (important for containers and cloud deployments!), their configure/compilation arguments and output, and so on.
1. Learn all the required tools and their requirements, the syntax of their respectful configs and read a ton of documentation to just install all of them.
2. Learn the basics of Nix and spin a server with centralized configuration with unified syntax, which is also resistant to my sloppiness ("I don't know what I'm doing" situation).
No need to specify which path was taken. Wasn't easy, but no regrets yet. Would love to switch to Guix since Guile seems much saner (at least easier to quickly understand) for a non-CS guy like myself, but support and package availability is nowhere near, unfortunately.
As a side note how is it possible that you were neither a sysadmin nor coder, yet were in the position to manage a server with VMs managed by libvirt? And how did you know Nix existed, or that you wanted to manage the machines with a central configuration server/repository to start with?
Recent years have shown how badly we need to trust our software, and Nix/Guix are two prime examples of projects trying to tackle this issue.
"Just shoot it" servers lack trust and reliability (assuming you are not shooting a reproducible distro of course :p).
Above the VM layer (@ the sandboxed process i.e. container layer), TUF[0] + Notary[1] + compliant image registries + attestation tools are helping to solve this problem which is nice.
The vast majority of Guix users are on other (so-called "foreign") distributions (i.e. not GuixSD) -- I think the opposite is true for Nix/NixOS.
I'm not sure what's "sticky" about it, can you elaborate?
There was also an issue with nix and docker compatibility that I ran into w/ nix-docker[0], but I don't remember what it was.
Here are some videos I found in my history back when I was exploring Nix (watched in end of 2017/early 2018 I believe):
https://www.youtube.com/watch?v=YbUPdv03ciI
https://www.youtube.com/watch?v=mIxtBVKo7JE
It's entirely possible my anecdata is too old to be useful. Maybe nix is much easier to use (and use correctly) these days. One example of where Nix should have been able to pick up mindshare is with the same people who value linuxkit[1]. Maybe this is is another marketing/branding/hype/money disparity thing but `nix-build '<something>' -A vm` looks like exactly what linuxkit is being lauded/promoted for being a good tool for, and it's been around for so much longer.
All of these (Nix/Guix/NginX Lua, etc) config systems are all so complex with layers of interesting syntax and punctuation.
Why can't these use simpler (INI/YAML/TOML/CSON or even JSON) configuration schemes? It would reduce barrier to entry - simplify parsing and automation, and a whole lot of other things. Why do I need to learn yet another language just to configure and manage my system?
Because you inevitably need something less simple at some point. It's a hard balance to strike. Want only a config format? Get angry advanced users. Want only a programming language? Get angry beginners. Want both? Get a hodge-podge of half-and-half configs calling out to built extensions and in general a bunch of beginners finding poor code-based solutions on the internet.
In general, you need a simple programming language to manage this stuff or it becomes unwieldy once it leaves hobbyist size. And mixing config formats and full-blown languages (or worse, template languages) just adds ambiguity on the best way to do something coupled with loose synchronization between the two formats, "extension hell", and half-developed code solutions with an exponential number of poorly tested combinations of exported features that beginners try to use. To see examples of all these problems, one simply has to look at the historical landscape of orchestration engines and build tools.
> [Nix is] so complex with layers of interesting syntax and puncation
Precisely. Guix uses Scheme all over the place. It's just _one_ language for everything, not multiple languages. As a result, it's easier.
Scheme yields very easy-to-read declarations (see https://ambrevar.xyz/guix-packaging for some examples), so JSON & friends don't add much here.
> Parsing and automation
Parsing couldn't be simpler than using the language itself! There is no need to write an interpreter here.
> Why do I need to learn yet another language just to configure and manage my system?
That's precisely part of my thesis: with Guix, you only need to know Lisp/Scheme (which users might already know since it's a general-purpose language). Programs going for a DSL are effectively forcing everyone to learn a language for the sole sake of using the programs.
Now think of a lisp that uses YAML as its syntax instead of sexprs. That might be a much better choice than msbuild, but do you really want that? Would that make things better?
.deploy: &deploy
and foo
<<:*deploy
etc. This doesn't simplify parsing. This is already a DSL. And the format changes slightly depending on implementations (official, gitlab,…).In fact packages in Nix are functions. Dependencies are just function arguments. It makes a lot of sense.
Here's a Nix example (I'm less familiar with Guix) which defines a Haskell package, where the definition is fetched from hackage.haskell.org, automatically converted to a Nix definition (using `cabal2nix` behind the scenes), with its test suite disabled and profiling symbols compiled in:
with import <nixpkgs> {}; # The Nix standard library
with haskell.lib; # Haskell-specific Nix functions
with haskellPackages; # Haskell packages, for use as dependencies
enableLibraryProfiling (dontCheck (callHackage "vector" "0.9") {})
I'd hate to think how to define such packages if Nix didn't have the ability to write functions like `enableLibraryProfiling`, `dontCheck` and `callHackage`.None of the formats you mention (JSON, YAML, etc.) support functions, either defining them or calling them. Adding functions to such formats would be problematic in two ways: figuring out how to make them work (representations, syntax, implementation, etc.) would be a challenge in itself, especially if we don't want to break existing tools for those formats; actually using them presents another problem, since functions are used so extensively that it would be pretty much like learning a new language anyway, which defeats the main reason of going down this route.
Note that Nix and Guix can offload some configuration to those more limited formats if desired, e.g. by using things like `readFile` and `fromJSON` in Nix. Personally, whenever I've done this I've inevitably wanted something more powerful, and ended up using Nix to generate the JSON; hence I don't bother these days!
>Lack of support for multiple package version, or “dependency hell”. Say, when the latest mpv requires a new ffmpeg, but upgrading ffmpeg breaks most other programs relying on it, we are stuck we dilemma: either we break some packages or we stick to older versions of other packages. Worse, a program could end up not being packaged or support by the OS at all. This issue is inherent to most distributions which can simply not provide the guarantee to fulfill their primary objective: package any program.
I disagree. Having multiple versions of a package means having old versions of a package, and that's something most users should not be messing with because they are not in a position to track and backport security fixes.
It's always undesirable to have to a dependency on an old, probably unsupported version of a library. The distributions that do it have a correspondingly huge maintenance burden. One of the advantages (from my point of view) of a lighter rolling distribution like Arch is that because all the software on the system is expected to be compatible with a library version that is upstream-supported, there is significantly less maintenance work to be done. Note that this is compatible with, say, packaging both GTK2 and GTK3 programs, since both of those are supported upstream. The OS is perfectly compatible with shipping multiple versions of a library, but Arch sensibly (IMO) chooses not to do so by default.
One way to quickly experience the pain points of the OP's way of doing things is to try to use or distribute software written in a language with a "modern" build tool like npm or cargo. These systems implicitly encourage hardcoding a single version (or a small set of versions) as dependencies, and the convenience of this means that many developers rarely update the list even if the new library versions are fully compatible with their code. So as the user building the software, or someone who wants to distribute it, you can either run with libraries that have known vulnerabilities, or you can update the libraries yourself and run an unsupported configuration, hoping you don't break anything in the process. A more reasonable position is that it is a bug if your program crashes with the latest version of a library.
This makes sense for actively maintained code.
There are a lot of pieces of software that aren't actively maintained but that don't exhibit any breaking bugs and people continue to rely on them. If the libraries that these pieces of software ever make breaking changes, either (a) someone has to step up and start maintaining the software again, (b) an older version of the library must be installed, or (c) the software dropped, annoying a lot of people who still depend on the tool.
What macOS has is .frameworks, which let you version shared dynamic libraries. When building a project against a framework, one can either choose to build against a specific version or (more commonly) leave the version unspecified and use the latest. No fuss, no muss.
That still implies active maintenance, ie doing new builds.
If it's assumed to work with the "latest version", but then breaks in the future, it is a decision outside of the build itself as to which version of the library it should link up with.
The only thing that should be baked into the software is which specific version of the dynamic lib it was compatible with, then externally the system can determine which most-recent version of the library is still compatible.
Not every update is important. Hell, I'd say most aren't, since developers are freely mixing security patches with feature updates. Until the culture changes to cleanly separate the two, all updates will carry the risk of degrading or breaking things.
> These systems [npm or cargo] implicitly encourage hardcoding a single version (or a small set of versions) as dependencies, and the convenience of this means that many developers rarely update the list even if the new library versions are fully compatible with their code.
Counterpoint: version pinning prevents your project from suddenly breaking apart at unexpected times, because some dependency had a breaking change. It also prevents you from automatically pulling in vulnerabilities introduced - sometimes intentionally - in the newer version. NodeJS in particular has a "malicious package" drama roughly every 6 months. In all honesty, you should be auditing your dependencies anyway, and it's harder to keep up if they change faster than you can review them.
Don't believe me? You're using a computer right now. Doubtless you are running both hardware and software that have had vulnerabilities exposed in the past and almost certainly have vulnerabilities right now that haven't been exposed yet. You use them anyway because at the end of the day shit needs to get done.
That's why being able to run out of date things is important to people in the real world.
The article says "Guix is a fork of Nix", but this is not correct. Guix uses the same format for derivations (~ a low-level representation of builds), so that it can reuse the Nix daemon, but that doesn't make it a fork.
Guix builds upon the very same idea of functional package management that was pioneered with Nix, so they are very close and they do have shared roots. But that's not what "fork" is usually understood to mean.
Here's something I wrote a few months ago (with minor changes) to clarify the relationship between these two projects. I hope this helps.
-------------------
As one of the co-maintainers of GNU Guix I'm obviously biased, but here's what I consider some important unique features of Guix:
- Guix is all written in Guile Scheme (with the exception of parts of the inherited daemon, which hasn't yet been completely implemented in Guile); this extends to development tools like importers, updaters, to user tools like "guix environment", and even bleeds into other projects that are used by GuixSD (the GNU system distribution built around Guix), such as the shepherd init system. There is a lot of code reuse across the stack, which makes hacking on Guix really fun and smooth.
- Packages are first class citizens in Guix. In Nix the idea of functional package management is very obvious in the way that packages are defined, namely as functions. These functions take their concrete inputs from an enormous mapping. In Guix you define first-class package values as Scheme variables. These package values reference other package values, which leads to a lazily constructed graph of packages. This emergent graph can be used as a library to trivially build other tools like "guix graph" (for visualising the graph in various ways) or "guix web" (for a web interface to installing and searching packages), "guix refresh" (for updating package definitions), a lovely feature-rich Emacs interface etc.
- Embedded DSL. Since Guix is written in Scheme---a language for writing languages---it was an obvious choice to embed the package DSL in the host language Scheme instead of implementing a separate language that needs a custom interpreter. This is great for hacking on Guix, because you can use all the tools you'd use for Scheme hacking. There's a REPL, great Emacs support, a debugger, etc. With its support for hygienic macros, Scheme is also a perfect vehicle to implement features like monads (we use a monadic interface for talking to the daemon) and to implement other convenient abstractions.
- Graph rewriting. Having everything defined as regular Scheme values means that you can almost trivially go through the package graph and rewrite things, e.g. to replace one variant of a package with a different one. Your software environment is just a Scheme value and can be inspected or precisely modified with a simple Scheme API.
- Code staging. Thanks to different ways of quoting code (plain S-expressions and package-aware G-expressions), we use Scheme at all stages: on the "host side" as well as on the "build side". Instead of gluing together shell snippets to be run by the daemon we work with the AST of Scheme code at all stages. If you're interested in code staging I recommend reading this paper: https://hal.inria.fr/hal-01580582/en
- Bootstrapping. Some of us are very active in the "bootstrappable builds" community (see http://bootstrappable.org) and are working towards full bootstrap paths for self-hosting compilers and build systems. One result is a working bootstrap path of the JDK from C (using jikes, GNU classpath, jamvm, icedtea, etc). In Guix we take bootstrapping problems serious and prefer to take the longer way to build things fully from source instead of just adding more binary blobs. This means that we cannot always package as many things as quickly as others (e.g. Java libraries are hard to build recursively from source). I'm currently working on bootstrapping GHC without GHC and without the generated C code, but via interpreting a variant of GHC with Hugs. Others are working on bootstrapping GCC via Scheme.
- GuixSD, the GNU system distribution built around Guix. GuixSD has many features that are very different from NixOS. The declarative configuration in Scheme includes system facilities, which also form a graph that can be inspected and extended; this allows for the definition of complex system facilities that abstract over co-dependent services and service configurations. GuixSD provides more Scheme APIs that apply to the whole system, turning your operating system into a Scheme library.
- I like the UI of Guix a lot more than that of Nix. With Nix 2.0 many perceived problems with the UI have been addressed, of course, but hey, I still prefer the Guix way. I also really like the Emacs interface, which is absolutely gorgeous. (What can I say, I live in Emacs and prefer rich 2D buffers over 1D command line strings.)
- It's what I want GNU to be. I'm a GNU hacker and to me Guix is a representative of a modern and innovative GNU. It's great to see more GNU projects acting as one within the context of Guix and GuixSD to provide an experience that is greater than the sum of its parts. Work on Guix affected other GNU packages such as the Hurd, Guile, Mes, cool Guile libraries, and led to a bunch of new GNU packages such as a workflow language for scientific computing.
On the other hand, although Guix has a lot of regular contributors and is very active, Nix currently has more contributors than Guix. Guix is a younger project. The tendency to take bootstrapping problems very seriously means that sometimes difficult packages require more work. Oddly, Guix seems to attract more Lispers than Haskellers (I'm a recovering Haskeller who fell in love with Scheme after watching the SICP lecture videos); it seems to be the other way around with Nix.
Having said all that: Nix and Guix are both implementations of functional package management. Both projects solve similar problems and both are active in the reproducible builds efforts. Solutions that were found by Nix devs sometimes make their way into Guix and vice versa. The projects are not competing with one another (there are orders of magnitudes more people out there who use neither Guix nor Nix than there are users of functional package managers, so there's no point in trying to get people who use Nix to switch to Guix). At our recent Guix fringe event before FOSDEM Eelco Dolstra (who invented functional package management and Nix) gave a talk on the future of Nix surrounded by Guix hackers --- there is no rivalry between these two projects.
Tell us about graph rebuild times.
When there's a security update to glibc and you do the equivalent of `apt-get upgrade` in Guix, how long does that generally take to complete?
We usually put changes that cause the world to be rebuilt on a separate branch and have the build farm build binaries for it. This can take quite a while, but it's not something a user generally needs to worry about.
I mean, how is this (Skribilo):
(define (freedom . body)
(ref :url "http://www.gnu.org/philosophy/free-sw.html" :text body))
(p [Skribilo is a ,(freedom [free]) document production tool that takes a structured document ...])
better than this (LaTeX): Skribilo is a \href{http://www.gnu.org/philosophy/free-sw.html}{free} document production tool that takes a structured document ... (p [Skribilo is a ,
(ref :url "http://www.gnu.org/philosophy/free-sw.html": text "free")
document production tool that takes a structured document ...])
vs\par Skribilo is a \href{http://www.gnu.org/philosophy/free-sw.html}{free} document production tool that takes a structured document ...
If we further examine
(ref :url "http://www.gnu.org/philosophy/free-sw.html":text "free")
\href{http://www.gnu.org/philosophy/free-sw.html}{free}
The first example defines a url with (ref :url :text) and latex is \href{}{} this is about the same amount of syntax being very similar to a function with 2 argumentsThe enclosing scope is (p []) so basically 5 extra characters to define structure.
I personally like S-expressions because they are very general and have deep semantic implications (eval-apply, a.k.a. code is data) that go beyond mere syntactic considerations.
Regarding your examples, if I understand correctly they are not equivalent, so they don't exactly compare.
Here LaTeX would require the \begin{document}...\end{document} bits.
But regardless, TeX is very painful to program with (lack of proper data structures and control structures). It's very important in my opinion.
But Lua(La)TeX exists, which allows for more user-friendly scripting in Lua (not my favourite language, but...), and I think that is the only real 'competitor' of (La)TeX.
I love Lisp, but the majority of what I write is in (La)TeX, and I don't know of anything comparable for dealing with creating and typesetting academic-type work. Most of its 'competitors' use TeX on the back-ends, and though I've tried writing more in Org mode and exporting to LaTeX, in the end for anything beyond trivial text, it's easier just to write directly in LaTeX.
I think there is a lot of hidden potential in Guix, especially with the choice of Guile as the language. The article demonstrates a bit of what you can do from Guile with some small script examples. A lot of the functionality of Guix is exposed and can be used to create tools and scripts. I sort of wonder what interesting tools and scripts will be made using this.
See this article for an introduction to the problems of attempting to match npm with principled package management:
Guix is also working on an installer to help reducing the friction. I'd personally like to work on a fully graphical install + package management.
While Guix sounds like some heavy scientific stuff, it really is a powerful base that allows anything to grow on top, including user-friendly interfaces.
The biggest thing that might be annoying for someone who is not comfortable with Lisp is probably the operating system configuration, which is done with Scheme. For installing packages, however, you can use the command line interface, or the convenient Emacs user interface --- neither of those require any programming knowledge.
Guix is from GNU, Scheme is their official extension language (with Guile as the implementation.)
Scheme is neat, and pretty, and very elegant, but it's not (even in its largest, most recent version) really meant for serious use on large systems. And I don't agree that it's a Lisp: it has only a single namespace, it breaks (car nil) → nil and (if nil "true" "false") → "false".
I'm aware that rms dislikes Lisp and wants Scheme to be GNU's extension language; IMHO he's wrong, and his attitude has really held back GNU, Emacs and the Lisp world at large. Had it not been for that attitude, we might have a Common Lisp Emacs by now, we might have a Common Lisp GNU userland by now, we might have a GNU which really is Not Unix, instead of a mess of C, security bugs & hacks.
Currently, Guix comes with pre-filled operating system declarations so that beside filling out the hostname and a few other options, there is little to do but run `guix system init`.
While Guix install is completely different from any other system (except Nix), it is suprisingly easy with nothing else but 2-3 steps (if you have Linux-libre compatible hardware, that is to say).
It’s hard to take screeds like this seriously when their suggested alternatives use LaTeX for output!
I only said it was a "better idea", not a "better finished product", but I should have been more explicit. Will fix.
What does this mean? Google is suggesting it has something to do with weed-whackers, and I'm guessing that's not right.
GUIX (I believe) has this "choose previous version from GRUB" dialog, so you can recover from bad init script by rolling back the whole thing. Any other OS will require manual fixes, and this is going to be quite a pain.
But limiting what people can do with build systems is generally a good thing.
I experimented with NixOS last year, liked it, and being long time Lisp user I would like to also try GuixSD. Would I have problems with CUDA, etc.?
There is a patch for a Tensorflow package, which is built without GPU support (because that requires CUDA), but it hasn't been merged yet, because it isn't really pretty. (I didn't use Bazel to build Tensorflow, because Bazel depends on dozens of Java archives that cannot easily be built exclusively from source.)
You can use Nix as an additional package manager on top of a Guix system, of course, but this might not be as satisfying as using one package manager exclusively.