„Nix ist JSON mit Funktionen." Heute die JSON-Hälfte – im nix repl live ausprobiert.
flake.nix und jede mkShell ist nur ein Nix-Ausdruck. Wer die Werte und
Strukturen der Sprache liest, liest auch jede Dev-Shell. Heute legst du das Fundament: Zahlen,
Strings, Listen, let … in.
nix replDie Sprache lernt man am schnellsten interaktiv. Starte die Read-Eval-Print-Schleife – sie wertet jeden Ausdruck sofort aus:
$ nix repl
nix-repl> 1 + 1
2
nix-repl> "hallo " + "welt"
"hallo welt"
Merksatz aus Lektion 1: Die Sprache wird ausgewertet. Eine ganze .nix-Datei ist
ein einziger Ausdruck, der zu einem Wert ausgewertet wird – kein
Skript aus Statements.
Wenn du JSON kennst, kennst du das meiste schon:
# Zahlen, Booleans, null
42 3.14 true null
# Strings – mit Interpolation via ${…}
"toolbox"
let name = "toolbox"; in "Projekt: ${name}" # => "Projekt: toolbox"
# Mehrzeilige Strings mit '' – Einrückung wird automatisch abgezogen
''
echo "hallo"
echo "aus dem shellHook"
''
./src oder /etc/hosts sind Pfade, keine Strings. Nix behandelt
sie speziell (relativ zur Datei, kopiert sie in den Store). Das wird wichtig, wenn wir später
src = ./.; für eigene Pakete schreiben.
Die Struktur, die dir in jeder Dev-Shell zuerst begegnet: die Liste der Pakete. Achtung – Elemente sind durch Leerzeichen getrennt, keine Kommas:
# eine Liste mit drei Strings
[ "git" "ripgrep" "jq" ]
# Listen dürfen gemischte Typen enthalten
[ 1 "a" true ]
# verketten mit ++
[ "git" ] ++ [ "jq" ] # => [ "git" "jq" ]
Genau so wird gleich die packages-Liste deiner mkShell aussehen – nur mit
echten Paketen statt Strings.
let … in: lokale Namen
Mit let gibst du Zwischenergebnissen Namen; in liefert den eigentlichen
Ergebnis-Ausdruck. Das hält große Beschreibungen lesbar:
let
pname = "toolbox";
version = "0.1.0";
in
"${pname}-${version}" # => "toolbox-0.1.0"
Die Namen aus dem let gelten nur im Ausdruck nach in – nicht außerhalb.
[ "a", "b" ] ist falsch. Richtig ist [ "a" "b" ]. Das Komma
ist der häufigste Anfängerfehler – Nix meldet dann einen kryptischen Syntaxfehler.
let braucht in
Jedes let endet mit einem in und genau einem Folge-Ausdruck. Vergisst du
in, bricht die Auswertung ab.
${…} funktioniert innerhalb eines Strings. Außerhalb schreibst du den
Ausdruck einfach direkt hin – kein ${} nötig.
Nicht spicken – Abrufen aus dem Gedächtnis ist genau die Übung, die hängen bleibt.
Wie trennt man Elemente in einer Nix-Liste?
[ "a" "b" "c" ]. Kommas gehören in Nix nicht in Listen; Semikolons trennen
Zuweisungen in Attribute-Sets (Lektion 3), nicht Listenelemente.
Wofür steht in im Ausdruck let … in …?
let bindet Namen, in sagt „und jetzt werte diesen Ausdruck mit den Namen
aus". Die Namen gelten nur dort. Mit Enthaltensein oder Import hat es nichts zu tun.
Was ergibt let n = "x"; in "log-${n}"?
${…} innerhalb eines Strings wird ausgewertet und eingesetzt: "log-x".
Außerhalb von Strings bräuchte man kein ${}.
Ziel: Im nix repl Werte, Listen und let kombinieren.
nix repl.let die Namen tool = "ripgrep" und ver = "14"."ripgrep@14" erzeugen.[ "git" "jq" ] und hänge per ++ noch "fd" an.Tipp: Im repl bestätigst du jede Zeile mit Enter; das Ergebnis wird sofort gezeigt.
nix-repl> let tool = "ripgrep"; ver = "14"; in "${tool}@${ver}"
"ripgrep@14"
nix-repl> [ "git" "jq" ] ++ [ "fd" ]
[ "git" "jq" "fd" ]
Genau diese drei Bausteine – Strings, Interpolation, Listen – tragen später deine Dev-Shell.
with, inherit, Funktionen)