⟰ Some NixOS Notes
⟸ Some NixOS Notes
⟹ Modules
Nix Manual: Part IV. Writing Nix Expressions
NixOS Wiki: Nix Expression Language
Nix is a lazy, purely functional language which you’ll be using for packages and configuration in NixOS. It has:
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/pull/45
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
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
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.
# 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; }