2022-08-01 12:20:45 -04:00
|
|
|
|
# Reading the Nix language without fear
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
The Nix language is used to declare packages and configurations for the Nix package manager.
|
|
|
|
|
|
|
|
|
|
You will quickly encounter Nix language expressions that may look very complicated.
|
2022-08-01 07:42:25 -04:00
|
|
|
|
Yet, the language has only few basic constructs which can be combined arbitrarily.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 07:42:25 -04:00
|
|
|
|
## What will you learn?
|
|
|
|
|
|
|
|
|
|
This guide should enable you to read typical Nix language code and understand its structure.
|
|
|
|
|
|
2022-08-01 12:13:57 -04:00
|
|
|
|
It shows the most common and distingushing patterns in the Nix language:
|
2022-08-01 07:42:25 -04:00
|
|
|
|
|
|
|
|
|
- assigning names
|
|
|
|
|
- declaring and calling functions
|
|
|
|
|
- referencing file system paths
|
2022-08-01 12:34:53 -04:00
|
|
|
|
- working with character strings
|
2022-08-01 07:42:25 -04:00
|
|
|
|
- using built-in functions and the standard library
|
|
|
|
|
- declaring build inputs and build outputs
|
|
|
|
|
|
2022-08-01 12:13:57 -04:00
|
|
|
|
It *does not* explain all Nix language features in detail.
|
|
|
|
|
See the [Nix manual][manual-language] for a full language reference.
|
|
|
|
|
|
2022-08-01 07:42:25 -04:00
|
|
|
|
## What do you need?
|
|
|
|
|
|
|
|
|
|
- Familiarity with other programming languages
|
|
|
|
|
<!-- TODO: link to yet-to-be instructions on "how to read command line examples" -->
|
|
|
|
|
- Familiarity with Unix shell to read command line examples
|
|
|
|
|
- Install the Nix package manager to run the examples
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:14:15 -04:00
|
|
|
|
# Basic Concepts
|
|
|
|
|
|
|
|
|
|
Imagine the Nix language as *JSON with functions*.
|
|
|
|
|
|
|
|
|
|
The purpose of Nix language is to define structured data.
|
|
|
|
|
Functions help with conveniently producing more complex data, and assigning names allows manipulating complex data as units.
|
|
|
|
|
|
|
|
|
|
To that end, every valid piece of Nix language code is an *expression*.
|
|
|
|
|
Evaluating a Nix expression produces a single value.
|
|
|
|
|
Every Nix file (`.nix`) contains a single expression.
|
|
|
|
|
|
|
|
|
|
:::{note}
|
|
|
|
|
To *evaluate* means to transform an expression according to the language rules until no further simplification is possible.
|
|
|
|
|
:::
|
|
|
|
|
|
2022-08-01 07:41:22 -04:00
|
|
|
|
## Running examples
|
|
|
|
|
|
|
|
|
|
All examples in this guide are valid Nix files that you can run yourself
|
|
|
|
|
|
|
|
|
|
The following example is a Nix expression adding two numbers:
|
|
|
|
|
|
|
|
|
|
1 + 2
|
|
|
|
|
|
2022-08-01 12:21:18 -04:00
|
|
|
|
3
|
|
|
|
|
|
2022-08-01 07:41:22 -04:00
|
|
|
|
Use `nix-instantiate --eval` to evaluate the expression in a Nix file.
|
|
|
|
|
|
|
|
|
|
echo 1 + 2 > file.nix
|
|
|
|
|
|
|
|
|
|
nix-instantiate --eval file.nix
|
|
|
|
|
3
|
|
|
|
|
|
|
|
|
|
:::{note}
|
|
|
|
|
`nix-instantiate --eval` will evaluate `default.nix` if no file name is specified.
|
|
|
|
|
|
|
|
|
|
echo 1 + 2 > default.nix
|
|
|
|
|
|
|
|
|
|
nix-instantiate --eval
|
|
|
|
|
3
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
Use `nix repl` to evaluate Nix expressions interactively (by typing them on the command line):
|
|
|
|
|
|
|
|
|
|
nix repl
|
|
|
|
|
Welcome to Nix 2.5.1. Type :? for help.
|
|
|
|
|
|
|
|
|
|
nix-repl> 1 + 2
|
|
|
|
|
3
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
# Names
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
There are two ways to assign names to values in Nix: attribute sets and `let` expressions.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Assignments are denoted by a single equal sign (`=`).
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
## Attribute sets
|
|
|
|
|
|
|
|
|
|
Attribute sets are collections of name-value-pairs.
|
|
|
|
|
|
|
|
|
|
Together with primitive data types and lists, they work exactly like in JSON and look very similar.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Nix language:
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
string = "hello";
|
|
|
|
|
integer = 1;
|
|
|
|
|
float = 3.141;
|
|
|
|
|
bool = true;
|
|
|
|
|
null = null;
|
2022-08-01 12:34:53 -04:00
|
|
|
|
list = [ 1 "two" false ];
|
2022-07-15 07:45:03 -04:00
|
|
|
|
attribute-set = {
|
|
|
|
|
a = "hello";
|
|
|
|
|
b = 2;
|
|
|
|
|
c = 2.718;
|
|
|
|
|
d = false;
|
|
|
|
|
}; # comments are supported
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
JSON:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
{
|
|
|
|
|
"string": "hello",
|
|
|
|
|
"integer": 1,
|
|
|
|
|
"float": 3.141,
|
|
|
|
|
"bool": true,
|
|
|
|
|
"null": null,
|
|
|
|
|
"list": [1, "two", false],
|
|
|
|
|
"set": {
|
|
|
|
|
"a": "hello",
|
|
|
|
|
"b": 1,
|
|
|
|
|
"c": 2.718,
|
|
|
|
|
"d": false
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
:::{note}
|
|
|
|
|
- Attribute names usually do not need quotes.[^1]
|
|
|
|
|
- List elements are separated by white space.[^2]
|
|
|
|
|
:::
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
[^1]: Details: [Nix manual - attribute naming rules]()
|
|
|
|
|
[^2]: Details: [Nix manual - lists][manual-lists]
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
[manual-lists]: https://nixos.org/manual/nix/stable/expressions/language-values.html#lists
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
### Recursive attribute sets
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
You will sometimes see attribute sets declared with `rec` prepended.
|
|
|
|
|
This allows expressions in the attribute set to access other attribute names in the set.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Example:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
```nix
|
|
|
|
|
rec {
|
|
|
|
|
one = 1;
|
|
|
|
|
two = one + 1;
|
|
|
|
|
three = two + 1;
|
|
|
|
|
}
|
|
|
|
|
```
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
{ one = 1; three = 3; two = 2; }
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Counter-example:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
```nix
|
|
|
|
|
{
|
|
|
|
|
one = 1;
|
|
|
|
|
two = one + 1;
|
|
|
|
|
three = two + 1;
|
|
|
|
|
}
|
|
|
|
|
```
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
error: undefined variable 'one'
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
at «string»:3:9:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
2| one = 1;
|
|
|
|
|
3| two = one + 1;
|
|
|
|
|
| ^
|
|
|
|
|
4| three = two + 1;
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
See here why we recommend to avoid the {ref}`rec-expression` and prefer the `let` expression instead.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
## `let` expression
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Also known as “`let` binding” or “`let` … `in`”.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
`let` expressions allow assigning names to values for repeated use.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Example:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
let
|
|
|
|
|
a = 1;
|
|
|
|
|
in
|
|
|
|
|
a + a
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
2
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
As in attribute sets, names can be assigned in any order.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
In contrast to attribute sets, the expressions on the right of the assignment can refer to other assigned names.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Example:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
nix-repl> let
|
|
|
|
|
b = a + 1
|
|
|
|
|
a = 1;
|
|
|
|
|
in
|
|
|
|
|
a + b
|
|
|
|
|
3
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Only the expressions in the `let` expression can access the newly declared names.
|
|
|
|
|
We say: the bindings have local scope.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Example:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
```nix
|
|
|
|
|
{
|
|
|
|
|
a = let x = 1; in x;
|
|
|
|
|
b = x;
|
|
|
|
|
}
|
|
|
|
|
```
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
error: undefined variable 'x'
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
at «string»:3:7:
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
2| a = let x = 1; in x;
|
|
|
|
|
3| b = x;
|
|
|
|
|
| ^
|
|
|
|
|
4| }
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
<!-- TODO: exercise - use let to reuse a value in an attribute set -->
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
# Functions
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Functions are everywhere in the Nix language.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
## Arguments
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Nix functions take exactly one argument.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
x: x + 1
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Argument and function body are separated by a colon (`:`).
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Wherever you see a colon (`:`) in Nix language code:
|
|
|
|
|
- on its left is the function argument
|
|
|
|
|
- on its right is the function body.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Applying a function to an argument means writing the argument after the function.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Example
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
```nix
|
|
|
|
|
(x: x + 1) 1
|
|
|
|
|
```
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
2
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Nix functions have no name when declared.
|
|
|
|
|
We say they are anonymous, or call such a function a *lambda*.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
We can assign functions a name like any to other value.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = x: x + 1;
|
|
|
|
|
in
|
|
|
|
|
f 1
|
|
|
|
|
2
|
|
|
|
|
|
|
|
|
|
Arguments can be chained.
|
|
|
|
|
|
|
|
|
|
x: y: x + y
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
This can be used like a function that takes two arguments, but offers additional flexibility.
|
|
|
|
|
|
|
|
|
|
The above function takes one argument and returns a function `y: x + y` with `x` set to the passed value.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = x: y: x + y;
|
|
|
|
|
in
|
|
|
|
|
f 1
|
|
|
|
|
«lambda @ (string):2:8»
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
The `lambda` indicates the resulting value is an anonymous function.
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Applying that to another argument yields the inner body `x + y`, which can now be fully evaluated.
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = x: y: x + y;
|
|
|
|
|
in
|
|
|
|
|
f 1 2
|
|
|
|
|
3
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
<!-- TODO: exercise - assign the lambda a name and do something with it -->
|
|
|
|
|
|
|
|
|
|
## Keyword arguments
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Nix functions can explicitly take an attribute set as argument.
|
|
|
|
|
|
|
|
|
|
{a, b}: a + b
|
|
|
|
|
|
|
|
|
|
This is equivalent to
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
x: x.a + x.b
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
The argument defines the exact attributes that have to be in that set.
|
|
|
|
|
Leaving out or passing additional attributes is an error.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = {a, b}: a + b
|
|
|
|
|
in
|
|
|
|
|
f { a = 1; b = 2; }
|
|
|
|
|
3
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
## Default attributes
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Also known as “default arguments”.
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
Arguments can have default values for attributes, denoted with a question mark (`?`).
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
{a, b ? 0}: a + b
|
|
|
|
|
|
|
|
|
|
Attributes in the argument are not required if they have a default value.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = {a, b ? 0}: a + b
|
|
|
|
|
in
|
|
|
|
|
f { a = 1; }
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = {a ? 0, b ? 0}: a + b
|
|
|
|
|
in
|
|
|
|
|
f { } # empty attribute set
|
|
|
|
|
0
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
## Additional attributes
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
You can allow additional attributes with an ellipsis (`...`):
|
|
|
|
|
|
|
|
|
|
{a, b, ...}: a + b
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
f = {a, b, ...}: a + b
|
|
|
|
|
in
|
|
|
|
|
f { a = 1; b = 2; c = 3; }
|
|
|
|
|
3
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
## Named keyword arguments
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
Also known as “@ syntax” or “‘at’ syntax”.
|
|
|
|
|
|
2022-07-28 05:49:03 -04:00
|
|
|
|
{a, b, ...}@args: a + b + args.c
|
|
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
|
|
args@{a, b, ...}: a + b + args.c
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
where additional attributes are subsumed under a name.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
2022-07-28 05:49:03 -04:00
|
|
|
|
f = {a, b, ...}@args: a + b + args.c
|
2022-07-15 07:45:03 -04:00
|
|
|
|
in
|
2022-07-28 05:49:03 -04:00
|
|
|
|
f { a = 1; b = 2; c = 3; }
|
|
|
|
|
6
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
This can be useful if this remaining attribute set needs to be processed as a whole.
|
|
|
|
|
|
2022-08-01 12:34:53 -04:00
|
|
|
|
# File system paths
|
|
|
|
|
|
|
|
|
|
Nix language offers additional convenience for file system paths.[^3]
|
|
|
|
|
|
|
|
|
|
Absolute paths always start with a slash (`/`):
|
|
|
|
|
|
|
|
|
|
/absolute/path
|
|
|
|
|
|
|
|
|
|
Paths are relative when they contain at least one slash (`/`) but to not start with one.
|
|
|
|
|
They are relative to the file containing the expression:
|
|
|
|
|
|
|
|
|
|
./relative
|
|
|
|
|
|
|
|
|
|
relative/path
|
|
|
|
|
|
|
|
|
|
[^3]: Details: [Nix manual - primitive data types][manual-primitives]
|
|
|
|
|
|
|
|
|
|
## Search path
|
|
|
|
|
|
|
|
|
|
Also known as “angle bracket syntax”.
|
|
|
|
|
|
|
|
|
|
<nixpkgs>
|
|
|
|
|
|
|
|
|
|
The value of a named path is a file system path that depends on the contents of the [`$NIX_PATH`][NIX_PATH] environment variable.
|
|
|
|
|
|
|
|
|
|
In practice, `<nixpkgs>` points to the file system path of some revision of the [Nix package collection][nixpkgs].
|
|
|
|
|
For example, `<nixpkgs/lib>` points to the subdirectory `lib` of that file system path.
|
|
|
|
|
|
|
|
|
|
[NIX_PATH]: https://nixos.org/manual/nix/unstable/command-ref/env-common.html?highlight=nix_path#env-NIX_PATH
|
|
|
|
|
[nixpkgs]: https://github.org/NixOS/nixpkgs
|
|
|
|
|
[manual-primitives]: https://nixos.org/manual/nix/stable/expressions/language-values.html#primitives
|
|
|
|
|
|
|
|
|
|
# Character strings
|
|
|
|
|
|
|
|
|
|
<!-- TODO: introduction -->
|
|
|
|
|
|
|
|
|
|
## String interpolation
|
|
|
|
|
|
|
|
|
|
<!-- TODO: details -->
|
|
|
|
|
|
|
|
|
|
nix-repl> let
|
|
|
|
|
name = "Nix";
|
|
|
|
|
in
|
|
|
|
|
"hello ${name}"
|
|
|
|
|
"hello Nix"
|
|
|
|
|
|
|
|
|
|
## Indented strings
|
|
|
|
|
|
|
|
|
|
''
|
|
|
|
|
multi
|
|
|
|
|
line
|
|
|
|
|
string
|
|
|
|
|
''
|
|
|
|
|
|
|
|
|
|
You will recognize indented strings by *double single quotes*.
|
|
|
|
|
Equal amounts of prepended white space are trimmed from the result.
|
|
|
|
|
|
|
|
|
|
Example:
|
|
|
|
|
|
|
|
|
|
nix-repl> ''
|
|
|
|
|
one
|
|
|
|
|
two
|
|
|
|
|
three
|
|
|
|
|
''
|
|
|
|
|
"one\n two\n three\n"
|
|
|
|
|
|
|
|
|
|
See [escaping rules]().
|
|
|
|
|
|
|
|
|
|
<!-- TODO: built-ins and library -->
|
|
|
|
|
|
|
|
|
|
<!-- TODO: side effects - fetchers and derivations -->
|
2022-07-15 07:45:03 -04:00
|
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
|
|
As a programming language, Nix is
|
|
|
|
|
|
|
|
|
|
- *declarative*
|
|
|
|
|
|
|
|
|
|
It has no notion of executing sequential steps.
|
|
|
|
|
Dependencies between operations are established only through data.
|
|
|
|
|
|
|
|
|
|
- *purely functional*
|
|
|
|
|
|
|
|
|
|
Pure means: Nix does not change the value of declarations during computation – there are no variables, only names for immutable values.
|
|
|
|
|
|
|
|
|
|
Functional means: In Nix, functions are like any other value.
|
|
|
|
|
Functions can be assigned to names, taken as arguments, or returned by functions.
|
|
|
|
|
|
|
|
|
|
- *lazy*
|
|
|
|
|
|
|
|
|
|
It will only evaluate expressions when their result is needed.[^1]
|
|
|
|
|
|
2022-07-28 09:22:33 -04:00
|
|
|
|
- *dynamically typed*
|
|
|
|
|
|
|
|
|
|
Type errors are only detected when operations are actually evaluated.[^2]
|
|
|
|
|
|
2022-07-15 07:45:03 -04:00
|
|
|
|
- *purpose-built*
|
|
|
|
|
|
|
|
|
|
The Nix language only exists for the Nix package manager.
|
|
|
|
|
It is not intended for general purpose use.
|
|
|
|
|
|
2022-07-28 09:22:33 -04:00
|
|
|
|
[^1]: For example, the built-in function `throw` causes evaluation to stop. However, the following works, because `throw` is never evaluated:
|
|
|
|
|
|
|
|
|
|
nix-repl> let lazy = { a = "success"; b = builtins.throw "error"; }; in lazy.a
|
|
|
|
|
"success"
|
|
|
|
|
|
|
|
|
|
[^2]: For example, while one cannot add integers to strings, the error is only detected when trying to get the result:
|
|
|
|
|
|
|
|
|
|
nix-repl> let x = { a = 1 + "1"; b = 2; }; in x.b
|
|
|
|
|
2
|
|
|
|
|
|
|
|
|
|
nix-repl> let x = { a = 1 + "1"; b = 2; }; in x.a
|
|
|
|
|
error: cannot add a string to an integer
|
|
|
|
|
|
|
|
|
|
at «string»:1:19:
|
|
|
|
|
|
|
|
|
|
1| let x = { a = 1 + "1"; b = 2; }; in x.a
|
|
|
|
|
| ^
|
|
|
|
|
2|
|
|
|
|
|
|