• 168 Posts
  • 580 Comments
Joined 9 months ago
cake
Cake day: April 4th, 2025

help-circle

  • It is the best solution I know of. There is a reason that functional (that is, “preferring a side-effect-free programming style”, yet Turing-complete) programming languages are used in both Nix and Guix: Package definitions need to be side-effect-free, otherwise you quickly have a mess similar to what most build systems are. Further, package definitions should be lazy (that is, evaluated when used, not when defined), and it helps when type definitions can be inferred. The latter excludes alternatives like Scala, Haskell, and OCaml, so what you end up with will anyway be very similar to a Lisp.




  • I program in a lot of languages, including C, C++, Rust, Python, Java, and Lisps are not more difficult than the others. In fact, they tend to be more orthogonal: Scheme can express mote things than Python, e.g. with its continuations, but is much simpler and minimal at the same time. In Python, you have list comprehensions, generator expressions, generators, iterators, dictionary comprehensions - in Clojure you have lists and lazy sequences, period. Guile and Common Lisps like SBCL compile to native code, and are a lot faster than Python - SBCL is about as fast as modern Java - and so on.

    In addition, what your comment distorts is that C, for example, was conceived as “portable assembly”, while Lisps S-expressions were originally conceived as mathematical notation for algorithms - it was only later discovered that they can be compiled down to native code.

    But as I already mentioned, when it comes to Guix, one sees a lot of hate, misconceptions, and trolling, and one can ask why.



  • The key point here was not the exact syntax but the functional style. The ternary conditional operator, regardless how it’s written, is for sure functional style because it is an expression.

    And, it is sometimes objectively better to write

     val = retrieve_val(key) if is_present(key) else compute_val(key)
    

    than

    val = (is_present(key) and retrieve_val(key)) or compute_val(key)
    

    because functional style is clearer in such cases.

    (Edit:) And at the same time, it avoids to make an extra function for each occurence of

    def get_val(key):
        if is_present(key):
            return retrieve_val(key)
        else:
            return compute_val(key)
    

    Back to topic: Guix und Nix are pure-functional package managers, and Guix uses a (mostly) functional package declaration language, Scheme, because it works better.



  • For using it as a full distro (using Guix System), there are two options:

    1. Dual-boot your hardware into it. For this, you need compatible hardware - and because of requiring open-source drivers, you have to be more selective, like in the old Linux days. E.g. NVidia graphics cards won’t work (but some good AMD Radeon cards will do). Advantage is you have full control over your hardware.
    2. Just run it in a virtual machine, like GNOME Boxes, or virt-manager, or VirtualBox. This one is easy. I am using Arch this way, in a virtual machine on Debian, and this has several advantages. (I use the Guix package manager in both Debian and Arch).



  • It would be hard for me to prove that the authors of the PEP were not motivated by C (though the ? ternary operator stands out in C like a sore thumb, it is highly unusual for C as a whole, and it seems that it originated in Algol 60, a predecessor of C). Proving this would require a fair bit of software “archeology” or software history research, given that Lisp is from 1960 and C from 1962.

    According to Wikipedia, Python was originally influenced by ABC, Ada (?) ALGOL 68, APL, C,C++, CLU, Dylan, Haskell,Icon, Lisp,Modula-3, Perl, Standard ML. Of these, at least 5 (APL, Haskell, Lisp, Dylan, and Standard ML) are functional.

    But what I think here is that the text of that PEP 308 is not a scholar work of software history research. Its goal was to convince the audience, and the main audience were the Python contributor community. And the leader of them was Guido van Rossum, who is well known for not liking functional programming (in Python 3, the filter reduce function was removed because of that). And van Rossum was one of the two authors of the accepted PEP.







  • It has real advantages to use a well-defined, established, small but complete programming language.

    One is that the language has good documentation, is very orthogonal, and has few rough edges.

    Another is that Scheme/Guile is really useful as a general programming language. It does many things really good which Python is used a lot for. Also, because it strongly supports side-effect-free functional style, it is a far better language for prototyping programs and utilities in Rust - both stemming from Lambda Calculus (remember Rust is a child of OCaml with some Algol syntax). For example, in both languages near everything is an expression.

    And that feeds back again with using Scheme as a configuration language in Guix: A frequent problem with using special languages for regular users of such complex systems is that you use them a bit, learn a bit, accomplish one thing or two - and then, you need to do something else, with the result that you forget it all again. Using Scheme allows to use a small language that is useful for other things and that you can really master.


  • It is really not that difficult, more like getting used to it.

    Basically,

    b = atan(x, y)
    

    transforms to

    (define b (atan x y))
    

    or, if b is in a local scope,

    (let ((b (atan x y))
           ; local expressions 
           )
    

    For functions, say we have in Python:

     def square(x):
           return x * x
    

    This becomes:

    (define (square x)
           (* x x))
    

    because the last expression in a function becomes its return value (and “*” is just a function name).

    The other key thing is the functional style - but other languages have picked up that, too. In fact, Python has now at least a dozen characteristics that became first popular with lisps.

    For example,

    a = k if cond else j
    

    is not that different from

    (define a (if cond k j))
    


  • At work:

    • geometric computations in a Performance-sensitive optimization algorithm that was drafted in Python. After confirmation, the whole algorithm was rewritten to C++, which was fine since it was part of a large science experiment
    • rewriting / wrapping some middleware + APIs so that other people can transition new work to rust. The resulting interfaces turned out very pleasant to use!

    At home:

    • building command-line software for my Gemini PDA. This is an ARM device and Rust is far easier to cross-compile than C++.
    • Implementing a larger optimization & solver algorithm (a few thousand lines) which I coded some time ago in Clojure. Very easy to parallize.

  • So, here are the key features and decisions of Guix:

    1. Guix is a package manager that can (optionally) run on top of Linux distributions or other POSIX systems, like cargo, pip, conda or conan. In difference to the pip and cargo it is language-agnostic, supports many different build systems and languages, and features around 29000 packages now.
    2. Guix allows to define a fully reoroducible system. This works by using a declarative language for immutable versiond package descriptions, and by deriving any software from package definitions and a fixed version of the source code. In that, it is similar but much stricter than Nix and NixOS. The key point is that any software built, and all its dependencies, go back to unambigously, immutable versions of source code - and all inputs to the system are open source and can be reviewed.
    3. This allows it, and also makes it technically possible, that any software package can be re-built and run years later. To make this legally possible, the official distribution of Guix also demands all components to be open source (FOSS). This is also a key difference to NixOS and non-free variants of Guix, which allow non-free binary packages, but sacrifice reproducibility. (To illustrate: If you have a binary, proprietary scanner driver in NixOS, and the owning company practices planned obselescence and decides that you should buy their new hardware, and pulls that driver, you are out of luck. In Guix, this can’t happen.) (Note that as your own private conponents, you can define any package you like, you can also distribute your definitions. Non-free packages for Guix do exist, in the same way as you can buy and run Game software for Linux. Such nin-free software just can’t become part of the official Guix distribution, just like Amazon or Apple can’t sell their non-free software via Debian or the Linux kernel project).
    4. All inputs being open source also means that any software component can be reviewed, that mis-features such as privacy-invasive behaviour can be removed, and that it is hardly possible to hide malware in the system. Because this also applies recursively to all compilers and build tools, this solves also Thompson’s “Trusting Trust” problem. In fact, the whole system can be build from a 512 byte binary root (called MER). (Interestingly, that level of user control gets a lot of hate online – certain companies don’t seem to like it).
    5. Because it would take too long to build every user package from source every time, the produced packages are normally cached (while their correct binary content can be easily verified).
    6. The declarative description language for the packages is a well-defined, established, minimalist language called Scheme. This is a member of the Lisp family of languages. That Lisp is very well suited for declaratively building and configuring large systems has been proven with GNU Emacs, whose software is written in Emacs Lisp.
    7. The Scheme implementation used is called Guile. It has especially good support for the POSIX environment and has also much better-than-average interactive debugging capabilities compared to other Scheme implementations.
    8. Also worth noting is that the Guix project has superb online documentation.