- A piece of Nix code is an expression
- Evaluating a Nix expression produces a Nix value.
# enter nix repl
nix repl
Inside REPL
# quit repl
:q
#
- In Nix, linebreaks, indentations and additional spaces are for reader's convinience.
let x = 1; y = 1; in x + y # equivalent to let x=1; y=1; in x + y
Attributes
{
string = "hello";
integer = 1;
float = 3.141;
bool = true;
null = null;
list = [ 1 "two" false ];
attribute-set = {
a = "hello";
b = 2;
c = 2.718;
d = false;
}; # comments are supported
}
Notes:
- Lists are separated by spaces.
Recursive Attributes
rec {
one = 1;
two = one + 1;
three = two + 1;
}
Notes:
- Order does not matter.
rec
is required if recursive attribute.
let ... in ...
let
b = a + 1;
a = 1;
in
a + b
Notes:
- Allows for repeated usage of values.
- Order does not matter
let a=1;b=a-1 ...
is equivalent tolet b=a-1;a=1 ...
.
Attribute Access
# access
let
attrset = { a = { b = { c = 1; }; }; };
in
attrset.a.b.c
# assignment
{ a.b.c = 1; } # output { a = { b = { c = 1; }; }; }
with ...; ...
let
a = {
x = 1;
y = 2;
z = 3;
};
in
with a; [ x y z ]
# output [ 1 2 3 ]
Notes:
- Allows access to attributes without repeating reference to parent attribute set.
inherit ...
let
x = 1;
y = 2;
in
{
inherit x y; # equivalent to x = x; y = y;
}
# more complex example with attribute set
let
a = { x = 1; y = 2; };
in
{
inherit (a) x y; # equivalent to x = a.x; y = a.y;
}
Notes:
- Assigning value from existing scope in nested scope
String interpolation
let
a = "no";
c = "foo";
in
{
d = ${c};
"${a + " ${a + " ${a}"}"}" # output no no no
}
# indend and string
''
one
two
three
''
"multi\nline\nstring\n"
File System Paths
<nixpkgs> # lookup path (equivalent to /nix/var/nix/profiles/per-user/root/channels/nixpkgs)
Notes:
- Points to revision onf Nixpkgs on filesystem.
Functions take exactly 1 argument.
Function and body are separated by :
.
x: x + 1 # returns a lambda
# multiple arguments
x: y: x + y # uses nesting
# attribute set with default
{ a, b ? 0 }: a + b
# args@{ a, b, ... }: a + b + args.c
Calling Function
let
f = x: x.a;
in
f { a = 1; }
Since function and argument are separated by white space, sometimes parentheses (
)
xs are required to achieve the desired result.
Caution
let
f = x: x + 1;
a = 1;
in [ (f a) ]
# different to
let
f = x: x + 1;
a = 1;
in [ f a ]
Since function and argument are separated by white space, sometimes parentheses `(` `)`xs are required to achieve the desired result.
*Caution*
```nix
let
f = x: x + 1;
a = 1;
in [ (f a) ]
# different to
let
f = x: x + 1;
a = 1;
in [ f a ]
let
f = {a, b ? 0}: a + b;
in
f { a = 1; } # ok since defaultable b
Libraries
builtins
- basic functions (e.g.builtins.toString
) built in C++.import
- top level to import a.nix
file.pkgs.lib
- useful functions built in Nix.
Fetchers
builtins.fetchurl
, builtins.fetchTarball
, ..., builtins.fetchGit
- Evaluate a filesystem path to a Nix store.
Derivations are at the core of Nix:
- Nix language is used to describe derivations.
- Nix runs derivations to produce built results.
- Built results can be used for other derivations.
stend.Derivation
- creates a derivation that Nix will eventually build.
{ pkgs ? import <nixpkgs> {} }:
let
message = "hello world";
in
pkgs.mkShell {
buildInputs = with pkgs; [ cowsay ];
shellHook = ''
cowsay ${message}
'';
}
Notes
- Nix expression is a function.