Nix Speedrun
This section will cover some Nix language basics as fast as possible.
Comments
Data types
Every value in Nix has a type. Some basic types are:
16 # integer
3.14 # float
false # boolean
"Hello, world!" # string
''
This is also a string,
but over multiple lines!
''
Assign a value to a variable:
And then inject it into a string:
Nix also has compound values. This is a list:
You can mix different types in a list. This is an attribute set:
An attribute set is like an object. It is a collection of name-value-pairs called attributes. The expression above is equivalent to:
Evaluation
In Nix, everything is an expression that evaluates to a value. Create a hello.nix
-file with the following content:
Then, evaluate the file:
A let-expression allows you to define local variables for an expression:
let
alice = {
name = "Alice";
age = "26";
};
in
''
Her name is ${alice.name}.
She is ${alice.age} years old.
''
Functions
Functions have the following form:
The pattern specifies what the argument of the function must look like, and binds variables in the body to (parts of) the argument.
Functions can only have a single argument. For multiple arguments, nest functions:
let
isAllowedToDrive =
name: age:
if age >= 18 then "${name} is eligible to drive." else "${name} is too young to drive yet.";
in
isAllowedToDrive "Charlie" 19
It is common to pass multiple arguments in an attribute set instead. Since Nix is lazily evaluated, you can define multiple bindings in the same let-statement.
You can also set optional arguments by providing default values:
Let's look at one last example:
let
myFunc = { a, b, c }: a + b * c;
numbers = {
a = 1;
b = 2;
c = 3;
};
result = myFunc { a = numbers.a; b = numbers.b; c = numbers.c; };
in
result
Nix provides some syntactical sugar to simplify that function call. The with
keyword brings all attributes from an attribute set into the scope:
However, this syntax is discouraged. Use inherit
instead to explicitly list attributes to bring into the scope:
Builtin functions
Nix provides builtin functions by default through the global builtins
constant. For example, builtins.attrNames
gives you a list of all attributes of the given attribute set:
Yes, this means that attribute keys, though defined as variables, are available as strings.
Some builtins are so common that the builtins
prefix can be omitted. map
is a builtin function that applies a function to each element of a list.
# squares.nix
let
numbers = [ 5 2 1 4 3 ];
squares = map (n: n * n) numbers;
in
{
inherit numbers squares;
}
The import
function allows to separate the codebase into multiple files:
# sort.nix
let
results = import ./squares.nix; # paths have their own type
inherit (results) squares;
inherit (builtins) sort lessThan;
in
sort lessThan squares
The
sort
function can be found in the Nix manual.