The Nix Expression Language
Nix is a lazy, purely functional language which you'll be using to configure your system. Before we discuss configuration in detail, you should be familiar with its basic syntax.
Types
- Strings:
"Hello, world!" ''First Line Second Line ''
- Integers and Floating-Point Numbers:
1 3.14
- Filesystem Paths:
/path/to/file ./hardware-configuration.nix ./. #! current directory: just `./` is not valid #! paths in angle brackets search the contents of $NIX_PATH. $NIX_PATH can #! have {key}={value} entries for special prefixes. #! `<nixpkgs>` is the path to your system's local copy of `nixpkgs`, located #! at `/nix/var/nix/profiles/per-user/root/channels/nixos`, <nixpkgs/pkgs/tools/misc/cowsay> #! and `<nixos-config>` is the path `/etc/nixos/configuration.nix` <nixos-config>
- URLs (don't use these, they're
deprecated!):
https://github.com/NixOS/rfcs/blob/master/rfcs/0045-deprecate-url-syntax.md
- Booleans:
true false
- Null:
null;
- Lists, whose values can be any type:
[ 1 "two" [ 3.0 ] { four = 4; } ]
- Sets (like dicts, maps), whose keys are strings and whose values can be any
type:
{ a = 1; b = [ 2 ]; c = { x = 3; }; } #! keys can be quoted if they have special characters that can't be there #! normally { "blah..." = 1; } #! make sure you don't forget those semicolons!
- Functions, which take exactly one argument and return the result of exactly
one expression:
#! these commands are performed in `nix repl` if you want to try them yourself. f = n: n + 1 x = f 1 #: 2 #! you can use currying to create functions which take multiple arguments f = first: second: first + second x = f 1 2 #: 3 #! or you can destructure a set argument in the function declaration like so f = { first, second }: first + second x = f { first = 1; second = 2; } #: 3 #! you can also accept a set with unspecified extra attributes (...), and #! specify defaults for optional attributes (attrib ? default) f = { first, second ? 2, ... }: first + second x = f { first = 1; irrelevant = 5; } #: 3 #! and even access the whole set by name to get to those extra attributes #! (name@{ ... } or { ... }@name) f = input@{ first, second, ... }: first + second + input.third x = f { first = 1; second = 2; third = 3; } #: 6
Operators
set.x # attribute access
f x # function application
-x # numerical negation
# attribute existence testing (true if `set` contains an attribute `x`)
set ? x
list ++ list # list concatenation
x * y / z # multiplication and division
x + y - z # addition and subtraction
!a # logical negation
# set merging (a set with both sets' attributes, if both sets have an attribute
# with the same key then `set2` takes precedence)
set1 // set2
a<b<=c>=d>e # comparison
a == b != c # equality testing
a && b # logical conjunction
a || b # logical disjunction
# logical implication (if `a` is true, `b` needs to be true or else the result
# is false)
a -> b
Builtins
abort s # no return value. stop evaluation and print error string
baseNameOf s # part of `s` after its last '/' character
derivation inputs # a derivation. will be discussed later
dirOf s # part of `s` preceding `baseNameOf s`
fetchTarball url # path of unpacked .tar.(gz|xz|bz2) downloaded from `url`
import path # the expression at `path`
# whether `x` is null. this is deprecated because you can just write `x == null`
isNull x
map f list # list of each `f x` for each `x` in `list`
removeAttrs set list # `set` with each attribute in `list` removed
throw s # no return value. `abort s` but softer
toString x # `x` converted to a string
builtins # a set containing more builtins
The remaining built-in functions are kept in builtins
to prevent clutter. The
contents of that set are described in Nix Manual: 15.5. Built-in
Functions.
Other Features
# comments, as you've probably noticed, begin like this
/* multi-line comments, however,
use these */
# bring a set's attributes into scope
s = { a = 1; };
x = with s; [ a ]; #: [ 1 ]
# define some temporary local variables to use in an expression
x = let
a = 1;
b = 2;
in a + b; #: 3
# allow a set to reference its own attributes
x = rec {
a = 1;
b = a + 1;
}; #: { a = 1; b = 2; }
# inherit some variables from the surrounding scope
x = rec {
a = 1;
b = {
inherit a;
}
}; #: { a = 1; b = { a = 1; }; }
# or from another set
x = rec {
a = { b = 1; };
inherit (a) b;
}; #: { a = { b = 1; }; b = 1; }
see also Nix Manual: Part IV. Writing Nix Expressions or NixOS Wiki: Nix Expression Language