I think that Nix expression language is Turing complete. At least by the number of constructs, it seems so [1].
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.
What if there was a way to replace parenthesis with syntax? For instance, if you could declare your operating system as:
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).
Wisp provides a Python-like syntax for Scheme that gives you something very close to the above: http://draketo.de/english/wisp . (Though me and my editor don't view parentheses as an obstacle, quite the opposite...)
There you're replacing a configuration language that is executable Scheme, with what seems to be a declarative language, and converting to indentation syntax. That's a two-variable change.
The original S-exp syntax doesn't have to be an executable program in which you use Scheme operators like cons* .
The indentation-based notation, likewise, can retain the property that it's executable Scheme and reveals operations like cons* to the user.
The whole problem with that notation is that it isn't declarative. It's mean to execute. So to read it you have to know Guile functions like cons* . vim and packages% are actually variable bindings; vim undoubtedly stands for some package object defined elsewhere.
A Scheme-based configuration language that is executable Scheme is going to end up using the entire language, and be daunting to some IT person who just wants to reconfigure the distro and isn't a Scheme programmer. (Counterargument: a clean, dedicated configuration template language will likely sprout a way to run arbitrary Scheme code anyway.)
It's tempting to make things like this because they are quick and dirty. For instance, we could make an assembly language which is like this. (mov eax ebx) could be a call to a function called mov, and eax and ebx could be constants in Scheme itself. The function has the side effect of emitting the assembled code into some stream. We don't have to write any code which would walk, validate and translate the syntax of a Lisp-ified assembly language; we just let the programmer write code using the API we have provided and throw it into the path of the evaluator.
And we can have fun like (dotimes 13 (roll %ecx)) to emit 13 copies of an instruction.
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.
This post shows exactly what I mean: editing Lisp with a good editor is nice, however when you're bootstrapping a system sometimes the only tool available is vi (no even vim, just vi).
Try to find a close parenthesis after 8 function calls without syntax highlighting, or without your "hide parenthesis".
Nix syntax is quite simple to read even without any editor support. I did the whole bootstrapping of my current NixOS system only using vim without special support for Nix language and still got it right in my first try.
> This post shows exactly what I mean: editing Lisp with a good editor is nice, however when you're bootstrapping a system sometimes the only tool available is vi (no even vim, just vi).
Then I think you misunderstood. My point is that if you don't like parentheses, then don't use parentheses. Lisp doesn't care. Denote structure in whichever way you prefer, and convert that to/from s-expressions programatically.
Guix runs on Guile Scheme. I-expressions (which use indentation instead of parentheses, which I linked to in the post, https://srfi.schemers.org/srfi-49/srfi-49.html ) contains an implementaion for Guile right there in the spec. Likewise the code repos for Sweet expressions and Wisp (which also allow mixfix, braces, etc. and I also linked to in the post) seem to provide explicit Guile support too, alongside other systems (e.g. Racket) and standalone conversion scripts for compatability with any other s-expression system. Guile also has a built-in implementation of "curly-infix expressions" ( https://www.gnu.org/software/guile/manual/guile.html#SRFI_00... ).
That's 4 ways to use Guix without reading or writing any parentheses; one of which comes built-in. It's also pretty trivial (thanks to the simplicity of s-expressions) to make up your own alternative if you don't like any of these.
> Vi has % to jump to a matching parenthesis as pretty ancient feature.
I know. It helps, but it is far from being good enough. Making things like slurp is still a pain without proper editor support, and this is very common to do in Lisp.
> All the code you see here was written using little more than indentation via Lisp mode and % for paren matching:
Yeah, and K&R written Unix with only ed. My point still is valid: Nix is more readable than Lisp without proper editor support.
Also, any half decent Lisp dialect can tell you where an unbalanced parenthesis lies; you shouldn't have any difficulties hunting for this in a large file.
$ txr unbal.tl
unbal.tl:8: syntax error
unbal.tl:8: unterminated expression
unbal.tl:8: while parsing form starting at line 5
$ pr -Tn unbal.tl
1 (defun foo()
2
3 )
4
5 (defun bar()
6 (let (x)
7 )
I don't think this is a great error message. I use Clojure everyday and I still had to look 2 times to find the error.
If it was something like this, this would be much better:
Unmatched parenthesis from starting at line 5.
Maybe you wanted to do something like this?
1 (defun foo()
2
3 )
4
5 (defun bar()
6 (let (x)
7 )
^
This being a very basic code. In reality you will have multiple function calls inside more complicated functions (like a package definition in Guix), so you will end closing 10+ parenthesis and catching them can be hell.
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...