mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-25 07:16:17 +02:00
docs: split types from syntax (#11013)
move together all syntactic and semantic information into one page, and add a page on data types, which in turn links to the syntax and semantics. also split out the note on scoping rules into its own page. Co-authored-by: Ryan Hendrickson <ryan.hendrickson@alum.mit.edu>
This commit is contained in:
parent
f809edba4f
commit
a713476790
20 changed files with 1029 additions and 935 deletions
|
@ -238,12 +238,12 @@ const redirects = {
|
||||||
"attr-system": "language/derivations.html#attr-system",
|
"attr-system": "language/derivations.html#attr-system",
|
||||||
"ssec-derivation": "language/derivations.html",
|
"ssec-derivation": "language/derivations.html",
|
||||||
"ch-expression-language": "language/index.html",
|
"ch-expression-language": "language/index.html",
|
||||||
"sec-constructs": "language/constructs.html",
|
"sec-constructs": "language/syntax.html",
|
||||||
"sect-let-language": "language/constructs.html#let-language",
|
"sect-let-language": "language/syntax.html#let-expressions",
|
||||||
"ss-functions": "language/constructs.html#functions",
|
"ss-functions": "language/syntax.html#functions",
|
||||||
"sec-language-operators": "language/operators.html",
|
"sec-language-operators": "language/operators.html",
|
||||||
"table-operators": "language/operators.html",
|
"table-operators": "language/operators.html",
|
||||||
"ssec-values": "language/values.html",
|
"ssec-values": "language/types.html",
|
||||||
"gloss-closure": "glossary.html#gloss-closure",
|
"gloss-closure": "glossary.html#gloss-closure",
|
||||||
"gloss-derivation": "glossary.html#gloss-derivation",
|
"gloss-derivation": "glossary.html#gloss-derivation",
|
||||||
"gloss-deriver": "glossary.html#gloss-deriver",
|
"gloss-deriver": "glossary.html#gloss-deriver",
|
||||||
|
@ -335,11 +335,15 @@ const redirects = {
|
||||||
"ssec-relnotes-2.2": "release-notes/rl-2.2.html",
|
"ssec-relnotes-2.2": "release-notes/rl-2.2.html",
|
||||||
"ssec-relnotes-2.3": "release-notes/rl-2.3.html",
|
"ssec-relnotes-2.3": "release-notes/rl-2.3.html",
|
||||||
},
|
},
|
||||||
"language/values.html": {
|
"language/types.html": {
|
||||||
"simple-values": "#primitives",
|
"simple-values": "#primitives",
|
||||||
"lists": "#list",
|
"lists": "#list",
|
||||||
"strings": "#string",
|
"strings": "#string",
|
||||||
"attribute-sets": "#attribute-set",
|
"attribute-sets": "#attribute-set",
|
||||||
|
"type-number": "#type-int",
|
||||||
|
},
|
||||||
|
"language/syntax.html": {
|
||||||
|
"scoping-rules": "scoping.html",
|
||||||
},
|
},
|
||||||
"installation/installing-binary.html": {
|
"installation/installing-binary.html": {
|
||||||
"linux": "uninstall.html#linux",
|
"linux": "uninstall.html#linux",
|
||||||
|
|
|
@ -25,11 +25,12 @@
|
||||||
- [Store Types](store/types/index.md)
|
- [Store Types](store/types/index.md)
|
||||||
{{#include ./store/types/SUMMARY.md}}
|
{{#include ./store/types/SUMMARY.md}}
|
||||||
- [Nix Language](language/index.md)
|
- [Nix Language](language/index.md)
|
||||||
- [Data Types](language/values.md)
|
- [Data Types](language/types.md)
|
||||||
- [Language Constructs](language/constructs.md)
|
- [String context](language/string-context.md)
|
||||||
|
- [Syntax and semantics](language/syntax.md)
|
||||||
|
- [Scoping rules](language/scope.md)
|
||||||
- [String interpolation](language/string-interpolation.md)
|
- [String interpolation](language/string-interpolation.md)
|
||||||
- [Lookup path](language/constructs/lookup-path.md)
|
- [Lookup path](language/constructs/lookup-path.md)
|
||||||
- [String context](language/string-context.md)
|
|
||||||
- [Operators](language/operators.md)
|
- [Operators](language/operators.md)
|
||||||
- [Derivations](language/derivations.md)
|
- [Derivations](language/derivations.md)
|
||||||
- [Advanced Attributes](language/advanced-attributes.md)
|
- [Advanced Attributes](language/advanced-attributes.md)
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
/expressions/language-operators /language/operators 301!
|
/expressions/language-operators /language/operators 301!
|
||||||
/expressions/language-values /language/values 301!
|
/expressions/language-values /language/values 301!
|
||||||
/expressions/* /language/:splat 301!
|
/expressions/* /language/:splat 301!
|
||||||
|
/language/values /language/types 301!
|
||||||
|
/language/constructs /language/syntax 301!
|
||||||
|
|
||||||
/installation/installation /installation 301!
|
/installation/installation /installation 301!
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ Most Nix commands interpret the following environment variables:
|
||||||
- <span id="env-NIX_PATH">[`NIX_PATH`](#env-NIX_PATH)</span>
|
- <span id="env-NIX_PATH">[`NIX_PATH`](#env-NIX_PATH)</span>
|
||||||
|
|
||||||
A colon-separated list of directories used to look up the location of Nix
|
A colon-separated list of directories used to look up the location of Nix
|
||||||
expressions using [paths](@docroot@/language/values.md#type-path)
|
expressions using [paths](@docroot@/language/types.md#type-path)
|
||||||
enclosed in angle brackets (i.e., `<path>`),
|
enclosed in angle brackets (i.e., `<path>`),
|
||||||
e.g. `/home/eelco/Dev:/etc/nixos`. It can be extended using the
|
e.g. `/home/eelco/Dev:/etc/nixos`. It can be extended using the
|
||||||
[`-I` option](@docroot@/command-ref/opt-common.md#opt-I).
|
[`-I` option](@docroot@/command-ref/opt-common.md#opt-I).
|
||||||
|
|
|
@ -57,7 +57,7 @@ The arguments *args* map to store paths in a number of possible ways:
|
||||||
easy way to copy user environment elements from one profile to
|
easy way to copy user environment elements from one profile to
|
||||||
another.
|
another.
|
||||||
|
|
||||||
- If `--from-expression` is given, *args* are [Nix language functions](@docroot@/language/constructs.md#functions) that are called with the [default Nix expression] as their single argument.
|
- If `--from-expression` is given, *args* are [Nix language functions](@docroot@/language/syntax.md#functions) that are called with the [default Nix expression] as their single argument.
|
||||||
The derivations returned by those function calls are installed.
|
The derivations returned by those function calls are installed.
|
||||||
This allows derivations to be specified in an unambiguous way, which is necessary if there are multiple derivations with the same name.
|
This allows derivations to be specified in an unambiguous way, which is necessary if there are multiple derivations with the same name.
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ Most Nix commands accept the following command-line options:
|
||||||
|
|
||||||
This option is accepted by `nix-env`, `nix-instantiate`, `nix-shell` and `nix-build`.
|
This option is accepted by `nix-env`, `nix-instantiate`, `nix-shell` and `nix-build`.
|
||||||
When evaluating Nix expressions, the expression evaluator will automatically try to call functions that it encounters.
|
When evaluating Nix expressions, the expression evaluator will automatically try to call functions that it encounters.
|
||||||
It can automatically call functions for which every argument has a [default value](@docroot@/language/constructs.md#functions) (e.g., `{ argName ? defaultValue }: ...`).
|
It can automatically call functions for which every argument has a [default value](@docroot@/language/syntax.md#functions) (e.g., `{ argName ? defaultValue }: ...`).
|
||||||
|
|
||||||
With `--arg`, you can also call functions that have arguments without a default value (or override a default value).
|
With `--arg`, you can also call functions that have arguments without a default value (or override a default value).
|
||||||
That is, if the evaluator encounters a function with an argument named *name*, it will call it with value *value*.
|
That is, if the evaluator encounters a function with an argument named *name*, it will call it with value *value*.
|
||||||
|
|
|
@ -312,7 +312,7 @@
|
||||||
|
|
||||||
- [package attribute set]{#package-attribute-set}
|
- [package attribute set]{#package-attribute-set}
|
||||||
|
|
||||||
An [attribute set](@docroot@/language/values.md#attribute-set) containing the attribute `type = "derivation";` (derivation for historical reasons), as well as other attributes, such as
|
An [attribute set](@docroot@/language/types.md#attribute-set) containing the attribute `type = "derivation";` (derivation for historical reasons), as well as other attributes, such as
|
||||||
- attributes that refer to the files of a [package], typically in the form of [derivation outputs](#output),
|
- attributes that refer to the files of a [package], typically in the form of [derivation outputs](#output),
|
||||||
- attributes that declare something about how the package is supposed to be installed or used,
|
- attributes that declare something about how the package is supposed to be installed or used,
|
||||||
- other metadata or arbitrary attributes.
|
- other metadata or arbitrary attributes.
|
||||||
|
@ -325,9 +325,9 @@
|
||||||
|
|
||||||
See [String interpolation](./language/string-interpolation.md) for details.
|
See [String interpolation](./language/string-interpolation.md) for details.
|
||||||
|
|
||||||
[string]: ./language/values.md#type-string
|
[string]: ./language/types.md#type-string
|
||||||
[path]: ./language/values.md#type-path
|
[path]: ./language/types.md#type-path
|
||||||
[attribute name]: ./language/values.md#attribute-set
|
[attribute name]: ./language/types.md#attribute-set
|
||||||
|
|
||||||
- [base directory]{#gloss-base-directory}
|
- [base directory]{#gloss-base-directory}
|
||||||
|
|
||||||
|
|
|
@ -1,486 +0,0 @@
|
||||||
# Language Constructs
|
|
||||||
|
|
||||||
## Recursive sets
|
|
||||||
|
|
||||||
Recursive sets are like normal [attribute sets](./values.md#attribute-set), but the attributes can refer to each other.
|
|
||||||
|
|
||||||
> *rec-attrset* = `rec {` [ *name* `=` *expr* `;` `]`... `}`
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
rec {
|
|
||||||
x = y;
|
|
||||||
y = 123;
|
|
||||||
}.x
|
|
||||||
```
|
|
||||||
|
|
||||||
This evaluates to `123`.
|
|
||||||
|
|
||||||
Note that without `rec` the binding `x = y;` would
|
|
||||||
refer to the variable `y` in the surrounding scope, if one exists, and
|
|
||||||
would be invalid if no such variable exists. That is, in a normal
|
|
||||||
(non-recursive) set, attributes are not added to the lexical scope; in a
|
|
||||||
recursive set, they are.
|
|
||||||
|
|
||||||
Recursive sets of course introduce the danger of infinite recursion. For
|
|
||||||
example, the expression
|
|
||||||
|
|
||||||
```nix
|
|
||||||
rec {
|
|
||||||
x = y;
|
|
||||||
y = x;
|
|
||||||
}.x
|
|
||||||
```
|
|
||||||
|
|
||||||
will crash with an `infinite recursion encountered` error message.
|
|
||||||
|
|
||||||
## Let-expressions
|
|
||||||
|
|
||||||
A let-expression allows you to define local variables for an expression.
|
|
||||||
|
|
||||||
> *let-in* = `let` [ *identifier* = *expr* ]... `in` *expr*
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let
|
|
||||||
x = "foo";
|
|
||||||
y = "bar";
|
|
||||||
in x + y
|
|
||||||
```
|
|
||||||
|
|
||||||
This evaluates to `"foobar"`.
|
|
||||||
|
|
||||||
## Inheriting attributes
|
|
||||||
|
|
||||||
When defining an [attribute set](./values.md#attribute-set) or in a [let-expression](#let-expressions) it is often convenient to copy variables from the surrounding lexical scope (e.g., when you want to propagate attributes).
|
|
||||||
This can be shortened using the `inherit` keyword.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let x = 123; in
|
|
||||||
{
|
|
||||||
inherit x;
|
|
||||||
y = 456;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
is equivalent to
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let x = 123; in
|
|
||||||
{
|
|
||||||
x = x;
|
|
||||||
y = 456;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
and both evaluate to `{ x = 123; y = 456; }`.
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> This works because `x` is added to the lexical scope by the `let` construct.
|
|
||||||
|
|
||||||
It is also possible to inherit attributes from another attribute set.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
In this fragment from `all-packages.nix`,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
graphviz = (import ../tools/graphics/graphviz) {
|
|
||||||
inherit fetchurl stdenv libpng libjpeg expat x11 yacc;
|
|
||||||
inherit (xorg) libXaw;
|
|
||||||
};
|
|
||||||
|
|
||||||
xorg = {
|
|
||||||
libX11 = ...;
|
|
||||||
libXaw = ...;
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
libpng = ...;
|
|
||||||
libjpg = ...;
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
the set used in the function call to the function defined in
|
|
||||||
`../tools/graphics/graphviz` inherits a number of variables from the
|
|
||||||
surrounding scope (`fetchurl` ... `yacc`), but also inherits `libXaw`
|
|
||||||
(the X Athena Widgets) from the `xorg` set.
|
|
||||||
|
|
||||||
Summarizing the fragment
|
|
||||||
|
|
||||||
```nix
|
|
||||||
...
|
|
||||||
inherit x y z;
|
|
||||||
inherit (src-set) a b c;
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
is equivalent to
|
|
||||||
|
|
||||||
```nix
|
|
||||||
...
|
|
||||||
x = x; y = y; z = z;
|
|
||||||
a = src-set.a; b = src-set.b; c = src-set.c;
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
when used while defining local variables in a let-expression or while
|
|
||||||
defining a set.
|
|
||||||
|
|
||||||
In a `let` expression, `inherit` can be used to selectively bring specific attributes of a set into scope. For example
|
|
||||||
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let
|
|
||||||
x = { a = 1; b = 2; };
|
|
||||||
inherit (builtins) attrNames;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
names = attrNames x;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
is equivalent to
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let
|
|
||||||
x = { a = 1; b = 2; };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
names = builtins.attrNames x;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
both evaluate to `{ names = [ "a" "b" ]; }`.
|
|
||||||
|
|
||||||
## Functions
|
|
||||||
|
|
||||||
Functions have the following form:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
pattern: body
|
|
||||||
```
|
|
||||||
|
|
||||||
The pattern specifies what the argument of the function must look like,
|
|
||||||
and binds variables in the body to (parts of) the argument. There are
|
|
||||||
three kinds of patterns:
|
|
||||||
|
|
||||||
- If a pattern is a single identifier, then the function matches any
|
|
||||||
argument. Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let negate = x: !x;
|
|
||||||
concat = x: y: x + y;
|
|
||||||
in if negate true then concat "foo" "bar" else ""
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that `concat` is a function that takes one argument and returns
|
|
||||||
a function that takes another argument. This allows partial
|
|
||||||
parameterisation (i.e., only filling some of the arguments of a
|
|
||||||
function); e.g.,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
map (concat "foo") [ "bar" "bla" "abc" ]
|
|
||||||
```
|
|
||||||
|
|
||||||
evaluates to `[ "foobar" "foobla" "fooabc" ]`.
|
|
||||||
|
|
||||||
- A *set pattern* of the form `{ name1, name2, …, nameN }` matches a
|
|
||||||
set containing the listed attributes, and binds the values of those
|
|
||||||
attributes to variables in the function body. For example, the
|
|
||||||
function
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ x, y, z }: z + y + x
|
|
||||||
```
|
|
||||||
|
|
||||||
can only be called with a set containing exactly the attributes `x`,
|
|
||||||
`y` and `z`. No other attributes are allowed. If you want to allow
|
|
||||||
additional arguments, you can use an ellipsis (`...`):
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ x, y, z, ... }: z + y + x
|
|
||||||
```
|
|
||||||
|
|
||||||
This works on any set that contains at least the three named
|
|
||||||
attributes.
|
|
||||||
|
|
||||||
It is possible to provide *default values* for attributes, in
|
|
||||||
which case they are allowed to be missing. A default value is
|
|
||||||
specified by writing `name ? e`, where *e* is an arbitrary
|
|
||||||
expression. For example,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ x, y ? "foo", z ? "bar" }: z + y + x
|
|
||||||
```
|
|
||||||
|
|
||||||
specifies a function that only requires an attribute named `x`, but
|
|
||||||
optionally accepts `y` and `z`.
|
|
||||||
|
|
||||||
- An `@`-pattern provides a means of referring to the whole value
|
|
||||||
being matched:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
args@{ x, y, z, ... }: z + y + x + args.a
|
|
||||||
```
|
|
||||||
|
|
||||||
but can also be written as:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ x, y, z, ... } @ args: z + y + x + args.a
|
|
||||||
```
|
|
||||||
|
|
||||||
Here `args` is bound to the argument *as passed*, which is further
|
|
||||||
matched against the pattern `{ x, y, z, ... }`.
|
|
||||||
The `@`-pattern makes mainly sense with an ellipsis(`...`) as
|
|
||||||
you can access attribute names as `a`, using `args.a`, which was
|
|
||||||
given as an additional attribute to the function.
|
|
||||||
|
|
||||||
> **Warning**
|
|
||||||
>
|
|
||||||
> `args@` binds the name `args` to the attribute set that is passed to the function.
|
|
||||||
> In particular, `args` does *not* include any default values specified with `?` in the function's set pattern.
|
|
||||||
>
|
|
||||||
> For instance
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> let
|
|
||||||
> f = args@{ a ? 23, ... }: [ a args ];
|
|
||||||
> in
|
|
||||||
> f {}
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> is equivalent to
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> let
|
|
||||||
> f = args @ { ... }: [ (args.a or 23) args ];
|
|
||||||
> in
|
|
||||||
> f {}
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> and both expressions will evaluate to:
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> [ 23 {} ]
|
|
||||||
> ```
|
|
||||||
|
|
||||||
Note that functions do not have names. If you want to give them a name,
|
|
||||||
you can bind them to an attribute, e.g.,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let concat = { x, y }: x + y;
|
|
||||||
in concat { x = "foo"; y = "bar"; }
|
|
||||||
```
|
|
||||||
|
|
||||||
## Conditionals
|
|
||||||
|
|
||||||
Conditionals look like this:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
if e1 then e2 else e3
|
|
||||||
```
|
|
||||||
|
|
||||||
where *e1* is an expression that should evaluate to a Boolean value
|
|
||||||
(`true` or `false`).
|
|
||||||
|
|
||||||
## Assertions
|
|
||||||
|
|
||||||
Assertions are generally used to check that certain requirements on or
|
|
||||||
between features and dependencies hold. They look like this:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
assert e1; e2
|
|
||||||
```
|
|
||||||
|
|
||||||
where *e1* is an expression that should evaluate to a Boolean value. If
|
|
||||||
it evaluates to `true`, *e2* is returned; otherwise expression
|
|
||||||
evaluation is aborted and a backtrace is printed.
|
|
||||||
|
|
||||||
Here is a Nix expression for the Subversion package that shows how
|
|
||||||
assertions can be used:.
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ localServer ? false
|
|
||||||
, httpServer ? false
|
|
||||||
, sslSupport ? false
|
|
||||||
, pythonBindings ? false
|
|
||||||
, javaSwigBindings ? false
|
|
||||||
, javahlBindings ? false
|
|
||||||
, stdenv, fetchurl
|
|
||||||
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
|
|
||||||
}:
|
|
||||||
|
|
||||||
assert localServer -> db4 != null; ①
|
|
||||||
assert httpServer -> httpd != null && httpd.expat == expat; ②
|
|
||||||
assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); ③
|
|
||||||
assert pythonBindings -> swig != null && swig.pythonSupport;
|
|
||||||
assert javaSwigBindings -> swig != null && swig.javaSupport;
|
|
||||||
assert javahlBindings -> j2sdk != null;
|
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "subversion-1.1.1";
|
|
||||||
...
|
|
||||||
openssl = if sslSupport then openssl else null; ④
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The points of interest are:
|
|
||||||
|
|
||||||
1. This assertion states that if Subversion is to have support for
|
|
||||||
local repositories, then Berkeley DB is needed. So if the Subversion
|
|
||||||
function is called with the `localServer` argument set to `true` but
|
|
||||||
the `db4` argument set to `null`, then the evaluation fails.
|
|
||||||
|
|
||||||
Note that `->` is the [logical
|
|
||||||
implication](https://en.wikipedia.org/wiki/Truth_table#Logical_implication)
|
|
||||||
Boolean operation.
|
|
||||||
|
|
||||||
2. This is a more subtle condition: if Subversion is built with Apache
|
|
||||||
(`httpServer`) support, then the Expat library (an XML library) used
|
|
||||||
by Subversion should be same as the one used by Apache. This is
|
|
||||||
because in this configuration Subversion code ends up being linked
|
|
||||||
with Apache code, and if the Expat libraries do not match, a build-
|
|
||||||
or runtime link error or incompatibility might occur.
|
|
||||||
|
|
||||||
3. This assertion says that in order for Subversion to have SSL support
|
|
||||||
(so that it can access `https` URLs), an OpenSSL library must be
|
|
||||||
passed. Additionally, it says that *if* Apache support is enabled,
|
|
||||||
then Apache's OpenSSL should match Subversion's. (Note that if
|
|
||||||
Apache support is not enabled, we don't care about Apache's
|
|
||||||
OpenSSL.)
|
|
||||||
|
|
||||||
4. The conditional here is not really related to assertions, but is
|
|
||||||
worth pointing out: it ensures that if SSL support is disabled, then
|
|
||||||
the Subversion derivation is not dependent on OpenSSL, even if a
|
|
||||||
non-`null` value was passed. This prevents an unnecessary rebuild of
|
|
||||||
Subversion if OpenSSL changes.
|
|
||||||
|
|
||||||
## With-expressions
|
|
||||||
|
|
||||||
A *with-expression*,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
with e1; e2
|
|
||||||
```
|
|
||||||
|
|
||||||
introduces the set *e1* into the lexical scope of the expression *e2*.
|
|
||||||
For instance,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let as = { x = "foo"; y = "bar"; };
|
|
||||||
in with as; x + y
|
|
||||||
```
|
|
||||||
|
|
||||||
evaluates to `"foobar"` since the `with` adds the `x` and `y` attributes
|
|
||||||
of `as` to the lexical scope in the expression `x + y`. The most common
|
|
||||||
use of `with` is in conjunction with the `import` function. E.g.,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
with (import ./definitions.nix); ...
|
|
||||||
```
|
|
||||||
|
|
||||||
makes all attributes defined in the file `definitions.nix` available as
|
|
||||||
if they were defined locally in a `let`-expression.
|
|
||||||
|
|
||||||
The bindings introduced by `with` do not shadow bindings introduced by
|
|
||||||
other means, e.g.
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; ...
|
|
||||||
```
|
|
||||||
|
|
||||||
establishes the same scope as
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...
|
|
||||||
```
|
|
||||||
|
|
||||||
Variables coming from outer `with` expressions *are* shadowed:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
with { a = "outer"; };
|
|
||||||
with { a = "inner"; };
|
|
||||||
a
|
|
||||||
```
|
|
||||||
|
|
||||||
Does evaluate to `"inner"`.
|
|
||||||
|
|
||||||
## Comments
|
|
||||||
|
|
||||||
- Inline comments start with `#` and run until the end of the line.
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> # A number
|
|
||||||
> 2 # Equals 1 + 1
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> ```console
|
|
||||||
> 2
|
|
||||||
> ```
|
|
||||||
|
|
||||||
- Block comments start with `/*` and run until the next occurrence of `*/`.
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> /*
|
|
||||||
> Block comments
|
|
||||||
> can span multiple lines.
|
|
||||||
> */ "hello"
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> ```console
|
|
||||||
> "hello"
|
|
||||||
> ```
|
|
||||||
|
|
||||||
This means that block comments cannot be nested.
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> /* /* nope */ */ 1
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> ```console
|
|
||||||
> error: syntax error, unexpected '*'
|
|
||||||
>
|
|
||||||
> at «string»:1:15:
|
|
||||||
>
|
|
||||||
> 1| /* /* nope */ *
|
|
||||||
> | ^
|
|
||||||
> ```
|
|
||||||
|
|
||||||
Consider escaping nested comments and unescaping them in post-processing.
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> /* /* nested *\/ */ 1
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> ```console
|
|
||||||
> 1
|
|
||||||
> ```
|
|
||||||
|
|
||||||
## Scoping rules
|
|
||||||
|
|
||||||
Nix is [statically scoped](https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope), but with multiple scopes and shadowing rules.
|
|
||||||
|
|
||||||
* primary scope --- explicitly-bound variables
|
|
||||||
* [`let`](#let-expressions)
|
|
||||||
* [`inherit`](#inheriting-attributes)
|
|
||||||
* function arguments
|
|
||||||
|
|
||||||
* secondary scope --- implicitly-bound variables
|
|
||||||
* [`with`](#with-expressions)
|
|
||||||
Primary scope takes precedence over secondary scope.
|
|
||||||
See [`with`](#with-expressions) for a detailed example.
|
|
|
@ -4,7 +4,7 @@
|
||||||
>
|
>
|
||||||
> *lookup-path* = `<` *identifier* [ `/` *identifier* ]... `>`
|
> *lookup-path* = `<` *identifier* [ `/` *identifier* ]... `>`
|
||||||
|
|
||||||
A lookup path is an identifier with an optional path suffix that resolves to a [path value](@docroot@/language/values.md#type-path) if the identifier matches a search path entry.
|
A lookup path is an identifier with an optional path suffix that resolves to a [path value](@docroot@/language/types.md#type-path) if the identifier matches a search path entry.
|
||||||
|
|
||||||
The value of a lookup path is determined by [`builtins.nixPath`](@docroot@/language/builtin-constants.md#builtins-nixPath).
|
The value of a lookup path is determined by [`builtins.nixPath`](@docroot@/language/builtin-constants.md#builtins-nixPath).
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||||
|
|
||||||
### Required
|
### Required
|
||||||
|
|
||||||
- [`name`]{#attr-name} ([String](@docroot@/language/values.md#type-string))
|
- [`name`]{#attr-name} ([String](@docroot@/language/types.md#type-string))
|
||||||
|
|
||||||
A symbolic name for the derivation.
|
A symbolic name for the derivation.
|
||||||
It is added to the [store path] of the corresponding [store derivation] as well as to its [output paths](@docroot@/glossary.md#gloss-output-path).
|
It is added to the [store path] of the corresponding [store derivation] as well as to its [output paths](@docroot@/glossary.md#gloss-output-path).
|
||||||
|
@ -31,7 +31,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||||
> The store derivation's path will be `/nix/store/<hash>-hello.drv`.
|
> The store derivation's path will be `/nix/store/<hash>-hello.drv`.
|
||||||
> The [output](#attr-outputs) paths will be of the form `/nix/store/<hash>-hello[-<output>]`
|
> The [output](#attr-outputs) paths will be of the form `/nix/store/<hash>-hello[-<output>]`
|
||||||
|
|
||||||
- [`system`]{#attr-system} ([String](@docroot@/language/values.md#type-string))
|
- [`system`]{#attr-system} ([String](@docroot@/language/types.md#type-string))
|
||||||
|
|
||||||
The system type on which the [`builder`](#attr-builder) executable is meant to be run.
|
The system type on which the [`builder`](#attr-builder) executable is meant to be run.
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||||
>
|
>
|
||||||
> [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem) has the value of the [`system` configuration option], and defaults to the system type of the current Nix installation.
|
> [`builtins.currentSystem`](@docroot@/language/builtin-constants.md#builtins-currentSystem) has the value of the [`system` configuration option], and defaults to the system type of the current Nix installation.
|
||||||
|
|
||||||
- [`builder`]{#attr-builder} ([Path](@docroot@/language/values.md#type-path) | [String](@docroot@/language/values.md#type-string))
|
- [`builder`]{#attr-builder} ([Path](@docroot@/language/types.md#type-path) | [String](@docroot@/language/types.md#type-string))
|
||||||
|
|
||||||
Path to an executable that will perform the build.
|
Path to an executable that will perform the build.
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
- [`args`]{#attr-args} ([List](@docroot@/language/values.md#list) of [String](@docroot@/language/values.md#type-string))
|
- [`args`]{#attr-args} ([List](@docroot@/language/types.md#list) of [String](@docroot@/language/types.md#type-string))
|
||||||
|
|
||||||
Default: `[ ]`
|
Default: `[ ]`
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ It outputs an attribute set, and produces a [store derivation] as a side effect
|
||||||
> };
|
> };
|
||||||
> ```
|
> ```
|
||||||
|
|
||||||
- [`outputs`]{#attr-outputs} ([List](@docroot@/language/values.md#list) of [String](@docroot@/language/values.md#type-string))
|
- [`outputs`]{#attr-outputs} ([List](@docroot@/language/types.md#list) of [String](@docroot@/language/types.md#type-string))
|
||||||
|
|
||||||
Default: `[ "out" ]`
|
Default: `[ "out" ]`
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ This is an incomplete overview of language features, by example.
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
|
|
||||||
*Basic values ([primitives](@docroot@/language/values.md#primitives))*
|
*Basic values ([primitives](@docroot@/language/types.md#primitives))*
|
||||||
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
@ -71,7 +71,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [string](@docroot@/language/values.md#type-string)
|
A [string](@docroot@/language/types.md#type-string)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -102,7 +102,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [comment](@docroot@/language/constructs.md#comments).
|
A [comment](@docroot@/language/syntax.md#comments).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -130,7 +130,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Booleans](@docroot@/language/values.md#type-boolean)
|
[Booleans](@docroot@/language/types.md#type-boolean)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -142,7 +142,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Null](@docroot@/language/values.md#type-null) value
|
[Null](@docroot@/language/types.md#type-null) value
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -154,7 +154,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
An [integer](@docroot@/language/values.md#type-number)
|
An [integer](@docroot@/language/types.md#type-int)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -166,7 +166,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [floating point number](@docroot@/language/values.md#type-number)
|
A [floating point number](@docroot@/language/types.md#type-float)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -178,7 +178,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
An absolute [path](@docroot@/language/values.md#type-path)
|
An absolute [path](@docroot@/language/types.md#type-path)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -190,7 +190,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [path](@docroot@/language/values.md#type-path) relative to the file containing this Nix expression
|
A [path](@docroot@/language/types.md#type-path) relative to the file containing this Nix expression
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -202,7 +202,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A home [path](@docroot@/language/values.md#type-path). Evaluates to the `"<user's home directory>/.config"`.
|
A home [path](@docroot@/language/types.md#type-path). Evaluates to the `"<user's home directory>/.config"`.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -238,7 +238,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
An [attribute set](@docroot@/language/values.md#attribute-set) with attributes named `x` and `y`
|
An [attribute set](@docroot@/language/types.md#attribute-set) with attributes named `x` and `y`
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -262,7 +262,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [recursive set](@docroot@/language/constructs.md#recursive-sets), equivalent to `{ x = "foo"; y = "foobar"; }`.
|
A [recursive set](@docroot@/language/syntax.md#recursive-sets), equivalent to `{ x = "foo"; y = "foobar"; }`.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -278,7 +278,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Lists](@docroot@/language/values.md#list) with three elements.
|
[Lists](@docroot@/language/types.md#list) with three elements.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -362,7 +362,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Attribute selection](@docroot@/language/values.md#attribute-set) (evaluates to `1`)
|
[Attribute selection](@docroot@/language/types.md#attribute-set) (evaluates to `1`)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -374,7 +374,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Attribute selection](@docroot@/language/values.md#attribute-set) with default (evaluates to `3`)
|
[Attribute selection](@docroot@/language/types.md#attribute-set) with default (evaluates to `3`)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -410,7 +410,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Conditional expression](@docroot@/language/constructs.md#conditionals).
|
[Conditional expression](@docroot@/language/syntax.md#conditionals).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -422,7 +422,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
[Assertion](@docroot@/language/constructs.md#assertions) check (evaluates to `"yes!"`).
|
[Assertion](@docroot@/language/syntax.md#assertions) check (evaluates to `"yes!"`).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -434,7 +434,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
Variable definition. See [`let`-expressions](@docroot@/language/constructs.md#let-expressions).
|
Variable definition. See [`let`-expressions](@docroot@/language/syntax.md#let-expressions).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -448,7 +448,7 @@ This is an incomplete overview of language features, by example.
|
||||||
|
|
||||||
Add all attributes from the given set to the scope (evaluates to `1`).
|
Add all attributes from the given set to the scope (evaluates to `1`).
|
||||||
|
|
||||||
See [`with`-expressions](@docroot@/language/constructs.md#with-expressions) for details and shadowing caveats.
|
See [`with`-expressions](@docroot@/language/syntax.md#with-expressions) for details and shadowing caveats.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -462,7 +462,7 @@ This is an incomplete overview of language features, by example.
|
||||||
|
|
||||||
Adds the variables to the current scope (attribute set or `let` binding).
|
Adds the variables to the current scope (attribute set or `let` binding).
|
||||||
Desugars to `pkgs = pkgs; src = src;`.
|
Desugars to `pkgs = pkgs; src = src;`.
|
||||||
See [Inheriting attributes](@docroot@/language/constructs.md#inheriting-attributes).
|
See [Inheriting attributes](@docroot@/language/syntax.md#inheriting-attributes).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -476,14 +476,14 @@ This is an incomplete overview of language features, by example.
|
||||||
|
|
||||||
Adds the attributes, from the attribute set in parentheses, to the current scope (attribute set or `let` binding).
|
Adds the attributes, from the attribute set in parentheses, to the current scope (attribute set or `let` binding).
|
||||||
Desugars to `lib = pkgs.lib; stdenv = pkgs.stdenv;`.
|
Desugars to `lib = pkgs.lib; stdenv = pkgs.stdenv;`.
|
||||||
See [Inheriting attributes](@docroot@/language/constructs.md#inheriting-attributes).
|
See [Inheriting attributes](@docroot@/language/syntax.md#inheriting-attributes).
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
*[Functions](@docroot@/language/constructs.md#functions) (lambdas)*
|
*[Functions](@docroot@/language/syntax.md#functions) (lambdas)*
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -500,7 +500,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) that expects an integer and returns it increased by 1.
|
A [function](@docroot@/language/syntax.md#functions) that expects an integer and returns it increased by 1.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -512,7 +512,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
Curried [function](@docroot@/language/constructs.md#functions), equivalent to `x: (y: x + y)`. Can be used like a function that takes two arguments and returns their sum.
|
Curried [function](@docroot@/language/syntax.md#functions), equivalent to `x: (y: x + y)`. Can be used like a function that takes two arguments and returns their sum.
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -524,7 +524,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) call (evaluates to 101)
|
A [function](@docroot@/language/syntax.md#functions) call (evaluates to 101)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -536,7 +536,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) bound to a variable and subsequently called by name (evaluates to 103)
|
A [function](@docroot@/language/syntax.md#functions) bound to a variable and subsequently called by name (evaluates to 103)
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -548,7 +548,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attributes `x` and `y` and concatenates them
|
A [function](@docroot@/language/syntax.md#functions) that expects a set with required attributes `x` and `y` and concatenates them
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -560,7 +560,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y`
|
A [function](@docroot@/language/syntax.md#functions) that expects a set with required attribute `x` and optional `y`, using `"bar"` as default value for `y`
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -572,7 +572,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attributes `x` and `y` and ignores any other attributes
|
A [function](@docroot@/language/syntax.md#functions) that expects a set with required attributes `x` and `y` and ignores any other attributes
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -586,7 +586,7 @@ This is an incomplete overview of language features, by example.
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
A [function](@docroot@/language/constructs.md#functions) that expects a set with required attributes `x` and `y`, and binds the whole set to `args`
|
A [function](@docroot@/language/syntax.md#functions) that expects a set with required attributes `x` and `y`, and binds the whole set to `args`
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
| Logical disjunction (`OR`) | *bool* <code>\|\|</code> *bool* | left | 13 |
|
| Logical disjunction (`OR`) | *bool* <code>\|\|</code> *bool* | left | 13 |
|
||||||
| [Logical implication] | *bool* `->` *bool* | right | 14 |
|
| [Logical implication] | *bool* `->` *bool* | right | 14 |
|
||||||
|
|
||||||
[string]: ./values.md#type-string
|
[string]: ./types.md#type-string
|
||||||
[path]: ./values.md#type-path
|
[path]: ./types.md#type-path
|
||||||
[number]: ./values.md#type-number
|
[number]: ./types.md#type-float <!-- TODO(@rhendric, #10970): rationalize this -->
|
||||||
[list]: ./values.md#list
|
[list]: ./types.md#list
|
||||||
[attribute set]: ./values.md#attribute-set
|
[attribute set]: ./types.md#attribute-set
|
||||||
|
|
||||||
## Attribute selection
|
## Attribute selection
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@
|
||||||
Select the attribute denoted by attribute path *attrpath* from [attribute set] *attrset*.
|
Select the attribute denoted by attribute path *attrpath* from [attribute set] *attrset*.
|
||||||
If the attribute doesn’t exist, return the *expr* after `or` if provided, otherwise abort evaluation.
|
If the attribute doesn’t exist, return the *expr* after `or` if provided, otherwise abort evaluation.
|
||||||
|
|
||||||
An attribute path is a dot-separated list of [attribute names](./values.md#attribute-set).
|
An attribute path is a dot-separated list of [attribute names](./types.md#attribute-set).
|
||||||
|
|
||||||
> **Syntax**
|
> **Syntax**
|
||||||
>
|
>
|
||||||
|
@ -61,7 +61,7 @@ The result is a [Boolean] value.
|
||||||
|
|
||||||
See also: [`builtins.hasAttr`](@docroot@/language/builtins.md#builtins-hasAttr)
|
See also: [`builtins.hasAttr`](@docroot@/language/builtins.md#builtins-hasAttr)
|
||||||
|
|
||||||
[Boolean]: ./values.md#type-boolean
|
[Boolean]: ./types.md#type-boolean
|
||||||
|
|
||||||
[Has attribute]: #has-attribute
|
[Has attribute]: #has-attribute
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ All comparison operators are implemented in terms of `<`, and the following equi
|
||||||
- Numbers are type-compatible, see [arithmetic] operators.
|
- Numbers are type-compatible, see [arithmetic] operators.
|
||||||
- Floating point numbers only differ up to a limited precision.
|
- Floating point numbers only differ up to a limited precision.
|
||||||
|
|
||||||
[function]: ./constructs.md#functions
|
[function]: ./syntax.md#functions
|
||||||
|
|
||||||
[Equality]: #equality
|
[Equality]: #equality
|
||||||
|
|
||||||
|
|
14
doc/manual/src/language/scope.md
Normal file
14
doc/manual/src/language/scope.md
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# Scoping rules
|
||||||
|
|
||||||
|
Nix is [statically scoped](https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope), but with multiple scopes and shadowing rules.
|
||||||
|
|
||||||
|
* primary scope: explicitly-bound variables
|
||||||
|
* [`let`](./syntax.md#let-expressions)
|
||||||
|
* [`inherit`](./syntax.md#inheriting-attributes)
|
||||||
|
* [function](./syntax.md#functions) arguments
|
||||||
|
|
||||||
|
* secondary scope: implicitly-bound variables
|
||||||
|
* [`with`](./syntax.md#with-expressions)
|
||||||
|
|
||||||
|
Primary scope takes precedence over secondary scope.
|
||||||
|
See [`with`](./syntax.md#with-expressions) for a detailed example.
|
|
@ -111,7 +111,7 @@ It creates an [attribute set] representing the string context, which can be insp
|
||||||
|
|
||||||
[`builtins.hasContext`]: ./builtins.md#builtins-hasContext
|
[`builtins.hasContext`]: ./builtins.md#builtins-hasContext
|
||||||
[`builtins.getContext`]: ./builtins.md#builtins-getContext
|
[`builtins.getContext`]: ./builtins.md#builtins-getContext
|
||||||
[attribute set]: ./values.md#attribute-set
|
[attribute set]: ./types.md#attribute-set
|
||||||
|
|
||||||
## Clearing string contexts
|
## Clearing string contexts
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@ String interpolation is a language feature where a [string], [path], or [attribu
|
||||||
|
|
||||||
Such a construct is called *interpolated string*, and the expression inside is an [interpolated expression](#interpolated-expression).
|
Such a construct is called *interpolated string*, and the expression inside is an [interpolated expression](#interpolated-expression).
|
||||||
|
|
||||||
[string]: ./values.md#type-string
|
[string]: ./types.md#type-string
|
||||||
[path]: ./values.md#type-path
|
[path]: ./types.md#type-path
|
||||||
[attribute set]: ./values.md#attribute-set
|
[attribute set]: ./types.md#attribute-set
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
841
doc/manual/src/language/syntax.md
Normal file
841
doc/manual/src/language/syntax.md
Normal file
|
@ -0,0 +1,841 @@
|
||||||
|
# Language Constructs
|
||||||
|
|
||||||
|
This section covers syntax and semantics of the Nix language.
|
||||||
|
|
||||||
|
## Basic Literals
|
||||||
|
|
||||||
|
### String {#string-literal}
|
||||||
|
|
||||||
|
*Strings* can be written in three ways.
|
||||||
|
|
||||||
|
The most common way is to enclose the string between double quotes, e.g., `"foo bar"`.
|
||||||
|
Strings can span multiple lines.
|
||||||
|
The results of other expressions can be included into a string by enclosing them in `${ }`, a feature known as [string interpolation].
|
||||||
|
|
||||||
|
[string interpolation]: ./string-interpolation.md
|
||||||
|
|
||||||
|
The following must be escaped to represent them within a string, by prefixing with a backslash (`\`):
|
||||||
|
|
||||||
|
- Double quote (`"`)
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> "\""
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "\""
|
||||||
|
|
||||||
|
- Backslash (`\`)
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> "\\"
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "\\"
|
||||||
|
|
||||||
|
- Dollar sign followed by an opening curly bracket (`${`) – "dollar-curly"
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> "\${"
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "\${"
|
||||||
|
|
||||||
|
The newline, carriage return, and tab characters can be written as `\n`, `\r` and `\t`, respectively.
|
||||||
|
|
||||||
|
A "double-dollar-curly" (`$${`) can be written literally.
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> "$${"
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "$\${"
|
||||||
|
|
||||||
|
String values are output on the terminal with Nix-specific escaping.
|
||||||
|
Strings written to files will contain the characters encoded by the escaping.
|
||||||
|
|
||||||
|
The second way to write string literals is as an *indented string*, which is enclosed between pairs of *double single-quotes* (`''`), like so:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
''
|
||||||
|
This is the first line.
|
||||||
|
This is the second line.
|
||||||
|
This is the third line.
|
||||||
|
''
|
||||||
|
```
|
||||||
|
|
||||||
|
This kind of string literal intelligently strips indentation from
|
||||||
|
the start of each line. To be precise, it strips from each line a
|
||||||
|
number of spaces equal to the minimal indentation of the string as a
|
||||||
|
whole (disregarding the indentation of empty lines). For instance,
|
||||||
|
the first and second line are indented two spaces, while the third
|
||||||
|
line is indented four spaces. Thus, two spaces are stripped from
|
||||||
|
each line, so the resulting string is
|
||||||
|
|
||||||
|
```nix
|
||||||
|
"This is the first line.\nThis is the second line.\n This is the third line.\n"
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> Whitespace and newline following the opening `''` is ignored if there is no non-whitespace text on the initial line.
|
||||||
|
|
||||||
|
> **Warning**
|
||||||
|
>
|
||||||
|
> Prefixed tab characters are not stripped.
|
||||||
|
>
|
||||||
|
> > **Example**
|
||||||
|
> >
|
||||||
|
> > The following indented string is prefixed with tabs:
|
||||||
|
> >
|
||||||
|
> > ''
|
||||||
|
> > all:
|
||||||
|
> > @echo hello
|
||||||
|
> > ''
|
||||||
|
> >
|
||||||
|
> > "\tall:\n\t\t@echo hello\n"
|
||||||
|
|
||||||
|
Indented strings support [string interpolation].
|
||||||
|
|
||||||
|
The following must be escaped to represent them in an indented string:
|
||||||
|
|
||||||
|
- `$` is escaped by prefixing it with two single quotes (`''`)
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> ''
|
||||||
|
> ''$
|
||||||
|
> ''
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "$\n"
|
||||||
|
|
||||||
|
- `''` is escaped by prefixing it with one single quote (`'`)
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> ''
|
||||||
|
> '''
|
||||||
|
> ''
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "''\n"
|
||||||
|
|
||||||
|
These special characters are escaped as follows:
|
||||||
|
- Linefeed (`\n`): `''\n`
|
||||||
|
- Carriage return (`\r`): `''\r`
|
||||||
|
- Tab (`\t`): `''\t`
|
||||||
|
|
||||||
|
`''\` escapes any other character.
|
||||||
|
|
||||||
|
A "double-dollar-curly" (`$${`) can be written literally.
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> ''
|
||||||
|
> $${
|
||||||
|
> ''
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> "$\${\n"
|
||||||
|
|
||||||
|
Indented strings are primarily useful in that they allow multi-line
|
||||||
|
string literals to follow the indentation of the enclosing Nix
|
||||||
|
expression, and that less escaping is typically necessary for
|
||||||
|
strings representing languages such as shell scripts and
|
||||||
|
configuration files because `''` is much less common than `"`.
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
...
|
||||||
|
postInstall =
|
||||||
|
''
|
||||||
|
mkdir $out/bin $out/etc
|
||||||
|
cp foo $out/bin
|
||||||
|
echo "Hello World" > $out/etc/foo.conf
|
||||||
|
${if enableBar then "cp bar $out/bin" else ""}
|
||||||
|
'';
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, as a convenience, *URIs* as defined in appendix B of
|
||||||
|
[RFC 2396](http://www.ietf.org/rfc/rfc2396.txt) can be written *as
|
||||||
|
is*, without quotes. For instance, the string
|
||||||
|
`"http://example.org/foo.tar.bz2"` can also be written as
|
||||||
|
`http://example.org/foo.tar.bz2`.
|
||||||
|
|
||||||
|
### Number {#number-literal}
|
||||||
|
|
||||||
|
<!-- TODO(@rhendric, #10970): split this into int and float -->
|
||||||
|
|
||||||
|
Numbers, which can be *integers* (like `123`) or *floating point*
|
||||||
|
(like `123.43` or `.27e13`).
|
||||||
|
|
||||||
|
See [arithmetic] and [comparison] operators for semantics.
|
||||||
|
|
||||||
|
[arithmetic]: ./operators.md#arithmetic
|
||||||
|
[comparison]: ./operators.md#comparison
|
||||||
|
|
||||||
|
### Path {#path-literal}
|
||||||
|
|
||||||
|
*Paths* are distinct from strings and can be expressed by path literals such as `./builder.sh`.
|
||||||
|
|
||||||
|
Paths are suitable for referring to local files, and are often preferable over strings.
|
||||||
|
- Path values do not contain trailing slashes, `.` and `..`, as they are resolved when evaluating a path literal.
|
||||||
|
- Path literals are automatically resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
|
||||||
|
- The files referred to by path values are automatically copied into the Nix store when used in a string interpolation or concatenation.
|
||||||
|
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
|
||||||
|
|
||||||
|
A path literal must contain at least one slash to be recognised as such.
|
||||||
|
For instance, `builder.sh` is not a path:
|
||||||
|
it's parsed as an expression that selects the attribute `sh` from the variable `builder`.
|
||||||
|
|
||||||
|
Path literals may also refer to absolute paths by starting with a slash.
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> Absolute paths make expressions less portable.
|
||||||
|
> In the case where a function translates a path literal into an absolute path string for a configuration file, it is recommended to write a string literal instead.
|
||||||
|
> This avoids some confusion about whether files at that location will be used during evaluation.
|
||||||
|
> It also avoids unintentional situations where some function might try to copy everything at the location into the store.
|
||||||
|
|
||||||
|
If the first component of a path is a `~`, it is interpreted such that the rest of the path were relative to the user's home directory.
|
||||||
|
For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`.
|
||||||
|
Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation.
|
||||||
|
|
||||||
|
Paths can be used in [string interpolation] and string concatenation.
|
||||||
|
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
|
||||||
|
|
||||||
|
Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
|
||||||
|
For example, assume you used a file path in an interpolated string during a `nix repl` session.
|
||||||
|
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents. Use `:r` to reset the repl as needed.
|
||||||
|
|
||||||
|
[store path]: @docroot@/store/store-path.md
|
||||||
|
|
||||||
|
Path literals can also include [string interpolation], besides being [interpolated into other expressions].
|
||||||
|
|
||||||
|
[interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions
|
||||||
|
|
||||||
|
At least one slash (`/`) must appear *before* any interpolated expression for the result to be recognized as a path.
|
||||||
|
|
||||||
|
`a.${foo}/b.${bar}` is a syntactically valid number division operation.
|
||||||
|
`./a.${foo}/b.${bar}` is a path.
|
||||||
|
|
||||||
|
[Lookup path](./constructs/lookup-path.md) literals such as `<nixpkgs>` also resolve to path values.
|
||||||
|
|
||||||
|
## List {#list-literal}
|
||||||
|
|
||||||
|
Lists are formed by enclosing a whitespace-separated list of values
|
||||||
|
between square brackets. For example,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
[ 123 ./foo.nix "abc" (f { x = y; }) ]
|
||||||
|
```
|
||||||
|
|
||||||
|
defines a list of four elements, the last being the result of a call to
|
||||||
|
the function `f`. Note that function calls have to be enclosed in
|
||||||
|
parentheses. If they had been omitted, e.g.,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
[ 123 ./foo.nix "abc" f { x = y; } ]
|
||||||
|
```
|
||||||
|
|
||||||
|
the result would be a list of five elements, the fourth one being a
|
||||||
|
function and the fifth being a set.
|
||||||
|
|
||||||
|
Note that lists are only lazy in values, and they are strict in length.
|
||||||
|
|
||||||
|
Elements in a list can be accessed using [`builtins.elemAt`](./builtins.md#builtins-elemAt).
|
||||||
|
|
||||||
|
## Attribute Set {#attrs-literal}
|
||||||
|
|
||||||
|
An attribute set is a collection of name-value-pairs (called *attributes*) enclosed in curly brackets (`{ }`).
|
||||||
|
|
||||||
|
An attribute name can be an identifier or a [string](#string).
|
||||||
|
An identifier must start with a letter (`a-z`, `A-Z`) or underscore (`_`), and can otherwise contain letters (`a-z`, `A-Z`), numbers (`0-9`), underscores (`_`), apostrophes (`'`), or dashes (`-`).
|
||||||
|
|
||||||
|
> **Syntax**
|
||||||
|
>
|
||||||
|
> *name* = *identifier* | *string* \
|
||||||
|
> *identifier* ~ `[a-zA-Z_][a-zA-Z0-9_'-]*`
|
||||||
|
|
||||||
|
Names and values are separated by an equal sign (`=`).
|
||||||
|
Each value is an arbitrary expression terminated by a semicolon (`;`).
|
||||||
|
|
||||||
|
> **Syntax**
|
||||||
|
>
|
||||||
|
> *attrset* = `{` [ *name* `=` *expr* `;` ]... `}`
|
||||||
|
|
||||||
|
Attributes can appear in any order.
|
||||||
|
An attribute name may only occur once.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
x = 123;
|
||||||
|
text = "Hello";
|
||||||
|
y = f { bla = 456; };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This defines a set with attributes named `x`, `text`, `y`.
|
||||||
|
|
||||||
|
Attributes can be accessed with the [`.` operator](./operators.md#attribute-selection).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ a = "Foo"; b = "Bar"; }.a
|
||||||
|
```
|
||||||
|
|
||||||
|
This evaluates to `"Foo"`.
|
||||||
|
|
||||||
|
It is possible to provide a default value in an attribute selection using the `or` keyword.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ a = "Foo"; b = "Bar"; }.c or "Xyzzy"
|
||||||
|
```
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ a = "Foo"; b = "Bar"; }.c.d.e.f.g or "Xyzzy"
|
||||||
|
```
|
||||||
|
|
||||||
|
will both evaluate to `"Xyzzy"` because there is no `c` attribute in the set.
|
||||||
|
|
||||||
|
You can use arbitrary double-quoted strings as attribute names:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ "$!@#?" = 123; }."$!@#?"
|
||||||
|
```
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let bar = "bar"; in
|
||||||
|
{ "foo ${bar}" = 123; }."foo ${bar}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Both will evaluate to `123`.
|
||||||
|
|
||||||
|
Attribute names support [string interpolation]:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let bar = "foo"; in
|
||||||
|
{ foo = 123; }.${bar}
|
||||||
|
```
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let bar = "foo"; in
|
||||||
|
{ ${bar} = 123; }.foo
|
||||||
|
```
|
||||||
|
|
||||||
|
Both will evaluate to `123`.
|
||||||
|
|
||||||
|
In the special case where an attribute name inside of a set declaration
|
||||||
|
evaluates to `null` (which is normally an error, as `null` cannot be coerced to
|
||||||
|
a string), that attribute is simply not added to the set:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ ${if foo then "bar" else null} = true; }
|
||||||
|
```
|
||||||
|
|
||||||
|
This will evaluate to `{}` if `foo` evaluates to `false`.
|
||||||
|
|
||||||
|
A set that has a `__functor` attribute whose value is callable (i.e. is
|
||||||
|
itself a function or a set with a `__functor` attribute whose value is
|
||||||
|
callable) can be applied as if it were a function, with the set itself
|
||||||
|
passed in first , e.g.,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let add = { __functor = self: x: x + self.x; };
|
||||||
|
inc = add // { x = 1; };
|
||||||
|
in inc 1
|
||||||
|
```
|
||||||
|
|
||||||
|
evaluates to `2`. This can be used to attach metadata to a function
|
||||||
|
without the caller needing to treat it specially, or to implement a form
|
||||||
|
of object-oriented programming, for example.
|
||||||
|
|
||||||
|
## Recursive sets
|
||||||
|
|
||||||
|
Recursive sets are like normal [attribute sets](./types.md#attribute-set), but the attributes can refer to each other.
|
||||||
|
|
||||||
|
> *rec-attrset* = `rec {` [ *name* `=` *expr* `;` `]`... `}`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
rec {
|
||||||
|
x = y;
|
||||||
|
y = 123;
|
||||||
|
}.x
|
||||||
|
```
|
||||||
|
|
||||||
|
This evaluates to `123`.
|
||||||
|
|
||||||
|
Note that without `rec` the binding `x = y;` would
|
||||||
|
refer to the variable `y` in the surrounding scope, if one exists, and
|
||||||
|
would be invalid if no such variable exists. That is, in a normal
|
||||||
|
(non-recursive) set, attributes are not added to the lexical scope; in a
|
||||||
|
recursive set, they are.
|
||||||
|
|
||||||
|
Recursive sets of course introduce the danger of infinite recursion. For
|
||||||
|
example, the expression
|
||||||
|
|
||||||
|
```nix
|
||||||
|
rec {
|
||||||
|
x = y;
|
||||||
|
y = x;
|
||||||
|
}.x
|
||||||
|
```
|
||||||
|
|
||||||
|
will crash with an `infinite recursion encountered` error message.
|
||||||
|
|
||||||
|
## Let-expressions
|
||||||
|
|
||||||
|
A let-expression allows you to define local variables for an expression.
|
||||||
|
|
||||||
|
> *let-in* = `let` [ *identifier* = *expr* ]... `in` *expr*
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
x = "foo";
|
||||||
|
y = "bar";
|
||||||
|
in x + y
|
||||||
|
```
|
||||||
|
|
||||||
|
This evaluates to `"foobar"`.
|
||||||
|
|
||||||
|
## Inheriting attributes
|
||||||
|
|
||||||
|
When defining an [attribute set](./types.md#attribute-set) or in a [let-expression](#let-expressions) it is often convenient to copy variables from the surrounding lexical scope (e.g., when you want to propagate attributes).
|
||||||
|
This can be shortened using the `inherit` keyword.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let x = 123; in
|
||||||
|
{
|
||||||
|
inherit x;
|
||||||
|
y = 456;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let x = 123; in
|
||||||
|
{
|
||||||
|
x = x;
|
||||||
|
y = 456;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and both evaluate to `{ x = 123; y = 456; }`.
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
>
|
||||||
|
> This works because `x` is added to the lexical scope by the `let` construct.
|
||||||
|
|
||||||
|
It is also possible to inherit attributes from another attribute set.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
In this fragment from `all-packages.nix`,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
graphviz = (import ../tools/graphics/graphviz) {
|
||||||
|
inherit fetchurl stdenv libpng libjpeg expat x11 yacc;
|
||||||
|
inherit (xorg) libXaw;
|
||||||
|
};
|
||||||
|
|
||||||
|
xorg = {
|
||||||
|
libX11 = ...;
|
||||||
|
libXaw = ...;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
libpng = ...;
|
||||||
|
libjpg = ...;
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
the set used in the function call to the function defined in
|
||||||
|
`../tools/graphics/graphviz` inherits a number of variables from the
|
||||||
|
surrounding scope (`fetchurl` ... `yacc`), but also inherits `libXaw`
|
||||||
|
(the X Athena Widgets) from the `xorg` set.
|
||||||
|
|
||||||
|
Summarizing the fragment
|
||||||
|
|
||||||
|
```nix
|
||||||
|
...
|
||||||
|
inherit x y z;
|
||||||
|
inherit (src-set) a b c;
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
```nix
|
||||||
|
...
|
||||||
|
x = x; y = y; z = z;
|
||||||
|
a = src-set.a; b = src-set.b; c = src-set.c;
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
when used while defining local variables in a let-expression or while
|
||||||
|
defining a set.
|
||||||
|
|
||||||
|
In a `let` expression, `inherit` can be used to selectively bring specific attributes of a set into scope. For example
|
||||||
|
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
x = { a = 1; b = 2; };
|
||||||
|
inherit (builtins) attrNames;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
names = attrNames x;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
is equivalent to
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let
|
||||||
|
x = { a = 1; b = 2; };
|
||||||
|
in
|
||||||
|
{
|
||||||
|
names = builtins.attrNames x;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
both evaluate to `{ names = [ "a" "b" ]; }`.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
Functions have the following form:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
pattern: body
|
||||||
|
```
|
||||||
|
|
||||||
|
The pattern specifies what the argument of the function must look like,
|
||||||
|
and binds variables in the body to (parts of) the argument. There are
|
||||||
|
three kinds of patterns:
|
||||||
|
|
||||||
|
- If a pattern is a single identifier, then the function matches any
|
||||||
|
argument. Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let negate = x: !x;
|
||||||
|
concat = x: y: x + y;
|
||||||
|
in if negate true then concat "foo" "bar" else ""
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that `concat` is a function that takes one argument and returns
|
||||||
|
a function that takes another argument. This allows partial
|
||||||
|
parameterisation (i.e., only filling some of the arguments of a
|
||||||
|
function); e.g.,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
map (concat "foo") [ "bar" "bla" "abc" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
evaluates to `[ "foobar" "foobla" "fooabc" ]`.
|
||||||
|
|
||||||
|
- A *set pattern* of the form `{ name1, name2, …, nameN }` matches a
|
||||||
|
set containing the listed attributes, and binds the values of those
|
||||||
|
attributes to variables in the function body. For example, the
|
||||||
|
function
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ x, y, z }: z + y + x
|
||||||
|
```
|
||||||
|
|
||||||
|
can only be called with a set containing exactly the attributes `x`,
|
||||||
|
`y` and `z`. No other attributes are allowed. If you want to allow
|
||||||
|
additional arguments, you can use an ellipsis (`...`):
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ x, y, z, ... }: z + y + x
|
||||||
|
```
|
||||||
|
|
||||||
|
This works on any set that contains at least the three named
|
||||||
|
attributes.
|
||||||
|
|
||||||
|
It is possible to provide *default values* for attributes, in
|
||||||
|
which case they are allowed to be missing. A default value is
|
||||||
|
specified by writing `name ? e`, where *e* is an arbitrary
|
||||||
|
expression. For example,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ x, y ? "foo", z ? "bar" }: z + y + x
|
||||||
|
```
|
||||||
|
|
||||||
|
specifies a function that only requires an attribute named `x`, but
|
||||||
|
optionally accepts `y` and `z`.
|
||||||
|
|
||||||
|
- An `@`-pattern provides a means of referring to the whole value
|
||||||
|
being matched:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
args@{ x, y, z, ... }: z + y + x + args.a
|
||||||
|
```
|
||||||
|
|
||||||
|
but can also be written as:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ x, y, z, ... } @ args: z + y + x + args.a
|
||||||
|
```
|
||||||
|
|
||||||
|
Here `args` is bound to the argument *as passed*, which is further
|
||||||
|
matched against the pattern `{ x, y, z, ... }`.
|
||||||
|
The `@`-pattern makes mainly sense with an ellipsis(`...`) as
|
||||||
|
you can access attribute names as `a`, using `args.a`, which was
|
||||||
|
given as an additional attribute to the function.
|
||||||
|
|
||||||
|
> **Warning**
|
||||||
|
>
|
||||||
|
> `args@` binds the name `args` to the attribute set that is passed to the function.
|
||||||
|
> In particular, `args` does *not* include any default values specified with `?` in the function's set pattern.
|
||||||
|
>
|
||||||
|
> For instance
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> let
|
||||||
|
> f = args@{ a ? 23, ... }: [ a args ];
|
||||||
|
> in
|
||||||
|
> f {}
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> is equivalent to
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> let
|
||||||
|
> f = args @ { ... }: [ (args.a or 23) args ];
|
||||||
|
> in
|
||||||
|
> f {}
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> and both expressions will evaluate to:
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> [ 23 {} ]
|
||||||
|
> ```
|
||||||
|
|
||||||
|
Note that functions do not have names. If you want to give them a name,
|
||||||
|
you can bind them to an attribute, e.g.,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let concat = { x, y }: x + y;
|
||||||
|
in concat { x = "foo"; y = "bar"; }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conditionals
|
||||||
|
|
||||||
|
Conditionals look like this:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
if e1 then e2 else e3
|
||||||
|
```
|
||||||
|
|
||||||
|
where *e1* is an expression that should evaluate to a Boolean value
|
||||||
|
(`true` or `false`).
|
||||||
|
|
||||||
|
## Assertions
|
||||||
|
|
||||||
|
Assertions are generally used to check that certain requirements on or
|
||||||
|
between features and dependencies hold. They look like this:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
assert e1; e2
|
||||||
|
```
|
||||||
|
|
||||||
|
where *e1* is an expression that should evaluate to a Boolean value. If
|
||||||
|
it evaluates to `true`, *e2* is returned; otherwise expression
|
||||||
|
evaluation is aborted and a backtrace is printed.
|
||||||
|
|
||||||
|
Here is a Nix expression for the Subversion package that shows how
|
||||||
|
assertions can be used:.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ localServer ? false
|
||||||
|
, httpServer ? false
|
||||||
|
, sslSupport ? false
|
||||||
|
, pythonBindings ? false
|
||||||
|
, javaSwigBindings ? false
|
||||||
|
, javahlBindings ? false
|
||||||
|
, stdenv, fetchurl
|
||||||
|
, openssl ? null, httpd ? null, db4 ? null, expat, swig ? null, j2sdk ? null
|
||||||
|
}:
|
||||||
|
|
||||||
|
assert localServer -> db4 != null; ①
|
||||||
|
assert httpServer -> httpd != null && httpd.expat == expat; ②
|
||||||
|
assert sslSupport -> openssl != null && (httpServer -> httpd.openssl == openssl); ③
|
||||||
|
assert pythonBindings -> swig != null && swig.pythonSupport;
|
||||||
|
assert javaSwigBindings -> swig != null && swig.javaSupport;
|
||||||
|
assert javahlBindings -> j2sdk != null;
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "subversion-1.1.1";
|
||||||
|
...
|
||||||
|
openssl = if sslSupport then openssl else null; ④
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The points of interest are:
|
||||||
|
|
||||||
|
1. This assertion states that if Subversion is to have support for
|
||||||
|
local repositories, then Berkeley DB is needed. So if the Subversion
|
||||||
|
function is called with the `localServer` argument set to `true` but
|
||||||
|
the `db4` argument set to `null`, then the evaluation fails.
|
||||||
|
|
||||||
|
Note that `->` is the [logical
|
||||||
|
implication](https://en.wikipedia.org/wiki/Truth_table#Logical_implication)
|
||||||
|
Boolean operation.
|
||||||
|
|
||||||
|
2. This is a more subtle condition: if Subversion is built with Apache
|
||||||
|
(`httpServer`) support, then the Expat library (an XML library) used
|
||||||
|
by Subversion should be same as the one used by Apache. This is
|
||||||
|
because in this configuration Subversion code ends up being linked
|
||||||
|
with Apache code, and if the Expat libraries do not match, a build-
|
||||||
|
or runtime link error or incompatibility might occur.
|
||||||
|
|
||||||
|
3. This assertion says that in order for Subversion to have SSL support
|
||||||
|
(so that it can access `https` URLs), an OpenSSL library must be
|
||||||
|
passed. Additionally, it says that *if* Apache support is enabled,
|
||||||
|
then Apache's OpenSSL should match Subversion's. (Note that if
|
||||||
|
Apache support is not enabled, we don't care about Apache's
|
||||||
|
OpenSSL.)
|
||||||
|
|
||||||
|
4. The conditional here is not really related to assertions, but is
|
||||||
|
worth pointing out: it ensures that if SSL support is disabled, then
|
||||||
|
the Subversion derivation is not dependent on OpenSSL, even if a
|
||||||
|
non-`null` value was passed. This prevents an unnecessary rebuild of
|
||||||
|
Subversion if OpenSSL changes.
|
||||||
|
|
||||||
|
## With-expressions
|
||||||
|
|
||||||
|
A *with-expression*,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
with e1; e2
|
||||||
|
```
|
||||||
|
|
||||||
|
introduces the set *e1* into the lexical scope of the expression *e2*.
|
||||||
|
For instance,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let as = { x = "foo"; y = "bar"; };
|
||||||
|
in with as; x + y
|
||||||
|
```
|
||||||
|
|
||||||
|
evaluates to `"foobar"` since the `with` adds the `x` and `y` attributes
|
||||||
|
of `as` to the lexical scope in the expression `x + y`. The most common
|
||||||
|
use of `with` is in conjunction with the `import` function. E.g.,
|
||||||
|
|
||||||
|
```nix
|
||||||
|
with (import ./definitions.nix); ...
|
||||||
|
```
|
||||||
|
|
||||||
|
makes all attributes defined in the file `definitions.nix` available as
|
||||||
|
if they were defined locally in a `let`-expression.
|
||||||
|
|
||||||
|
The bindings introduced by `with` do not shadow bindings introduced by
|
||||||
|
other means, e.g.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let a = 3; in with { a = 1; }; let a = 4; in with { a = 2; }; ...
|
||||||
|
```
|
||||||
|
|
||||||
|
establishes the same scope as
|
||||||
|
|
||||||
|
```nix
|
||||||
|
let a = 1; in let a = 2; in let a = 3; in let a = 4; in ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Variables coming from outer `with` expressions *are* shadowed:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
with { a = "outer"; };
|
||||||
|
with { a = "inner"; };
|
||||||
|
a
|
||||||
|
```
|
||||||
|
|
||||||
|
Does evaluate to `"inner"`.
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
- Inline comments start with `#` and run until the end of the line.
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> # A number
|
||||||
|
> 2 # Equals 1 + 1
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> ```console
|
||||||
|
> 2
|
||||||
|
> ```
|
||||||
|
|
||||||
|
- Block comments start with `/*` and run until the next occurrence of `*/`.
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> /*
|
||||||
|
> Block comments
|
||||||
|
> can span multiple lines.
|
||||||
|
> */ "hello"
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> ```console
|
||||||
|
> "hello"
|
||||||
|
> ```
|
||||||
|
|
||||||
|
This means that block comments cannot be nested.
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> /* /* nope */ */ 1
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> ```console
|
||||||
|
> error: syntax error, unexpected '*'
|
||||||
|
>
|
||||||
|
> at «string»:1:15:
|
||||||
|
>
|
||||||
|
> 1| /* /* nope */ *
|
||||||
|
> | ^
|
||||||
|
> ```
|
||||||
|
|
||||||
|
Consider escaping nested comments and unescaping them in post-processing.
|
||||||
|
|
||||||
|
> **Example**
|
||||||
|
>
|
||||||
|
> ```nix
|
||||||
|
> /* /* nested *\/ */ 1
|
||||||
|
> ```
|
||||||
|
>
|
||||||
|
> ```console
|
||||||
|
> 1
|
||||||
|
> ```
|
91
doc/manual/src/language/types.md
Normal file
91
doc/manual/src/language/types.md
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
# Data Types
|
||||||
|
|
||||||
|
Every value in the Nix language has one of the following types:
|
||||||
|
|
||||||
|
* [Integer](#type-int)
|
||||||
|
* [Float](#type-float)
|
||||||
|
* [Boolean](#type-bool)
|
||||||
|
* [String](#type-string)
|
||||||
|
* [Path](#type-path)
|
||||||
|
* [Null](#type-null)
|
||||||
|
* [Attribute set](#type-attrs)
|
||||||
|
* [List](#type-list)
|
||||||
|
* [Function](#type-function)
|
||||||
|
* [External](#type-external)
|
||||||
|
|
||||||
|
## Primitives
|
||||||
|
|
||||||
|
### Integer {#type-int}
|
||||||
|
|
||||||
|
An _integer_ in the Nix language is a signed 64-bit integer.
|
||||||
|
|
||||||
|
Non-negative integers can be expressed as [integer literals](syntax.md#number-literal).
|
||||||
|
Negative integers are created with the [arithmetic negation operator](./operators.md#arithmetic).
|
||||||
|
The function [`builtins.isInt`](builtins.md#builtins-isInt) can be used to determine if a value is an integer.
|
||||||
|
|
||||||
|
### Float {#type-float}
|
||||||
|
|
||||||
|
A _float_ in the Nix language is a 64-bit [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754) floating-point number.
|
||||||
|
|
||||||
|
Most non-negative floats can be expressed as [float literals](syntax.md#number-literal).
|
||||||
|
Negative floats are created with the [arithmetic negation operator](./operators.md#arithmetic).
|
||||||
|
The function [`builtins.isFloat`](builtins.md#builtins-isFloat) can be used to determine if a value is a float.
|
||||||
|
|
||||||
|
### Boolean {#type-bool}
|
||||||
|
|
||||||
|
A _boolean_ in the Nix language is one of _true_ or _false_.
|
||||||
|
|
||||||
|
<!-- TODO: mention the top-level environment -->
|
||||||
|
|
||||||
|
These values are available as attributes of [`builtins`](builtin-constants.md#builtins-builtins) as [`builtins.true`](builtin-constants.md#builtins-true) and [`builtins.false`](builtin-constants.md#builtins-false).
|
||||||
|
The function [`builtins.isBool`](builtins.md#builtins-isBool) can be used to determine if a value is a boolean.
|
||||||
|
|
||||||
|
### String {#type-string}
|
||||||
|
|
||||||
|
A _string_ in the Nix language is an immutable, finite-length sequence of bytes, along with a [string context](string-context.md).
|
||||||
|
Nix does not assume or support working natively with character encodings.
|
||||||
|
|
||||||
|
String values without string context can be expressed as [string literals](syntax.md#string-literal).
|
||||||
|
The function [`builtins.isString`](builtins.md#builtins-isString) can be used to determine if a value is a string.
|
||||||
|
|
||||||
|
### Path {#type-path}
|
||||||
|
|
||||||
|
<!-- TODO(@rhendric, #10970): Incorporate content from syntax.md#path-literal -->
|
||||||
|
|
||||||
|
The function [`builtins.isPath`](builtins.md#builtins-isPath) can be used to determine if a value is a path.
|
||||||
|
|
||||||
|
### Null {#type-null}
|
||||||
|
|
||||||
|
There is a single value of type _null_ in the Nix language.
|
||||||
|
|
||||||
|
<!-- TODO: mention the top-level environment -->
|
||||||
|
|
||||||
|
This value is available as an attribute on the [`builtins`](builtin-constants.md#builtins-builtins) attribute set as [`builtins.null`](builtin-constants.md#builtins-null).
|
||||||
|
|
||||||
|
## Compound values
|
||||||
|
|
||||||
|
### Attribute set {#type-attrs}
|
||||||
|
|
||||||
|
<!-- TODO(@rhendric, #10970): fill this out -->
|
||||||
|
|
||||||
|
An attribute set can be constructed with an [attribute set literal](syntax.md#attrs-literal).
|
||||||
|
The function [`builtins.isAttrs`](builtins.md#builtins-isAttrs) can be used to determine if a value is an attribute set.
|
||||||
|
|
||||||
|
### List {#type-list}
|
||||||
|
|
||||||
|
<!-- TODO(@rhendric, #10970): fill this out -->
|
||||||
|
|
||||||
|
A list can be constructed with a [list literal](syntax.md#list-literal).
|
||||||
|
The function [`builtins.isList`](builtins.md#builtins-isList) can be used to determine if a value is a list.
|
||||||
|
|
||||||
|
## Function {#type-function}
|
||||||
|
|
||||||
|
<!-- TODO(@rhendric, #10970): fill this out -->
|
||||||
|
|
||||||
|
A function can be constructed with a [function expression](syntax.md#functions).
|
||||||
|
The function [`builtins.isFunction`](builtins.md#builtins-isFunction) can be used to determine if a value is a function.
|
||||||
|
|
||||||
|
## External {#type-external}
|
||||||
|
|
||||||
|
An _external_ value is an opaque value created by a Nix [plugin](../command-ref/conf-file.md#conf-plugin-files).
|
||||||
|
Such a value can be substituted in Nix expressions but only created and used by plugin code.
|
|
@ -1,374 +0,0 @@
|
||||||
# Data Types
|
|
||||||
|
|
||||||
## Primitives
|
|
||||||
|
|
||||||
- <a id="type-string" href="#type-string">String</a>
|
|
||||||
|
|
||||||
*Strings* can be written in three ways.
|
|
||||||
|
|
||||||
The most common way is to enclose the string between double quotes, e.g., `"foo bar"`.
|
|
||||||
Strings can span multiple lines.
|
|
||||||
The results of other expressions can be included into a string by enclosing them in `${ }`, a feature known as [string interpolation].
|
|
||||||
|
|
||||||
[string interpolation]: ./string-interpolation.md
|
|
||||||
|
|
||||||
The following must be escaped to represent them within a string, by prefixing with a backslash (`\`):
|
|
||||||
|
|
||||||
- Double quote (`"`)
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> "\""
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "\""
|
|
||||||
|
|
||||||
- Backslash (`\`)
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> "\\"
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "\\"
|
|
||||||
|
|
||||||
- Dollar sign followed by an opening curly bracket (`${`) – "dollar-curly"
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> "\${"
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "\${"
|
|
||||||
|
|
||||||
The newline, carriage return, and tab characters can be written as `\n`, `\r` and `\t`, respectively.
|
|
||||||
|
|
||||||
A "double-dollar-curly" (`$${`) can be written literally.
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> "$${"
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "$\${"
|
|
||||||
|
|
||||||
String values are output on the terminal with Nix-specific escaping.
|
|
||||||
Strings written to files will contain the characters encoded by the escaping.
|
|
||||||
|
|
||||||
The second way to write string literals is as an *indented string*, which is enclosed between pairs of *double single-quotes* (`''`), like so:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
''
|
|
||||||
This is the first line.
|
|
||||||
This is the second line.
|
|
||||||
This is the third line.
|
|
||||||
''
|
|
||||||
```
|
|
||||||
|
|
||||||
This kind of string literal intelligently strips indentation from
|
|
||||||
the start of each line. To be precise, it strips from each line a
|
|
||||||
number of spaces equal to the minimal indentation of the string as a
|
|
||||||
whole (disregarding the indentation of empty lines). For instance,
|
|
||||||
the first and second line are indented two spaces, while the third
|
|
||||||
line is indented four spaces. Thus, two spaces are stripped from
|
|
||||||
each line, so the resulting string is
|
|
||||||
|
|
||||||
```nix
|
|
||||||
"This is the first line.\nThis is the second line.\n This is the third line.\n"
|
|
||||||
```
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> Whitespace and newline following the opening `''` is ignored if there is no non-whitespace text on the initial line.
|
|
||||||
|
|
||||||
> **Warning**
|
|
||||||
>
|
|
||||||
> Prefixed tab characters are not stripped.
|
|
||||||
>
|
|
||||||
> > **Example**
|
|
||||||
> >
|
|
||||||
> > The following indented string is prefixed with tabs:
|
|
||||||
> >
|
|
||||||
> > ''
|
|
||||||
> > all:
|
|
||||||
> > @echo hello
|
|
||||||
> > ''
|
|
||||||
> >
|
|
||||||
> > "\tall:\n\t\t@echo hello\n"
|
|
||||||
|
|
||||||
Indented strings support [string interpolation].
|
|
||||||
|
|
||||||
The following must be escaped to represent them in an indented string:
|
|
||||||
|
|
||||||
- `$` is escaped by prefixing it with two single quotes (`''`)
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> ''
|
|
||||||
> ''$
|
|
||||||
> ''
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "$\n"
|
|
||||||
|
|
||||||
- `''` is escaped by prefixing it with one single quote (`'`)
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> ''
|
|
||||||
> '''
|
|
||||||
> ''
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "''\n"
|
|
||||||
|
|
||||||
These special characters are escaped as follows:
|
|
||||||
- Linefeed (`\n`): `''\n`
|
|
||||||
- Carriage return (`\r`): `''\r`
|
|
||||||
- Tab (`\t`): `''\t`
|
|
||||||
|
|
||||||
`''\` escapes any other character.
|
|
||||||
|
|
||||||
A "double-dollar-curly" (`$${`) can be written literally.
|
|
||||||
|
|
||||||
> **Example**
|
|
||||||
>
|
|
||||||
> ```nix
|
|
||||||
> ''
|
|
||||||
> $${
|
|
||||||
> ''
|
|
||||||
> ```
|
|
||||||
>
|
|
||||||
> "$\${\n"
|
|
||||||
|
|
||||||
Indented strings are primarily useful in that they allow multi-line
|
|
||||||
string literals to follow the indentation of the enclosing Nix
|
|
||||||
expression, and that less escaping is typically necessary for
|
|
||||||
strings representing languages such as shell scripts and
|
|
||||||
configuration files because `''` is much less common than `"`.
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
...
|
|
||||||
postInstall =
|
|
||||||
''
|
|
||||||
mkdir $out/bin $out/etc
|
|
||||||
cp foo $out/bin
|
|
||||||
echo "Hello World" > $out/etc/foo.conf
|
|
||||||
${if enableBar then "cp bar $out/bin" else ""}
|
|
||||||
'';
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, as a convenience, *URIs* as defined in appendix B of
|
|
||||||
[RFC 2396](http://www.ietf.org/rfc/rfc2396.txt) can be written *as
|
|
||||||
is*, without quotes. For instance, the string
|
|
||||||
`"http://example.org/foo.tar.bz2"` can also be written as
|
|
||||||
`http://example.org/foo.tar.bz2`.
|
|
||||||
|
|
||||||
- <a id="type-number" href="#type-number">Number</a>
|
|
||||||
|
|
||||||
Numbers, which can be *integers* (like `123`) or *floating point*
|
|
||||||
(like `123.43` or `.27e13`).
|
|
||||||
|
|
||||||
See [arithmetic] and [comparison] operators for semantics.
|
|
||||||
|
|
||||||
[arithmetic]: ./operators.md#arithmetic
|
|
||||||
[comparison]: ./operators.md#comparison
|
|
||||||
|
|
||||||
- <a id="type-path" href="#type-path">Path</a>
|
|
||||||
|
|
||||||
*Paths* are distinct from strings and can be expressed by path literals such as `./builder.sh`.
|
|
||||||
|
|
||||||
Paths are suitable for referring to local files, and are often preferable over strings.
|
|
||||||
- Path values do not contain trailing slashes, `.` and `..`, as they are resolved when evaluating a path literal.
|
|
||||||
- Path literals are automatically resolved relative to their [base directory](@docroot@/glossary.md#gloss-base-directory).
|
|
||||||
- The files referred to by path values are automatically copied into the Nix store when used in a string interpolation or concatenation.
|
|
||||||
- Tooling can recognize path literals and provide additional features, such as autocompletion, refactoring automation and jump-to-file.
|
|
||||||
|
|
||||||
A path literal must contain at least one slash to be recognised as such.
|
|
||||||
For instance, `builder.sh` is not a path:
|
|
||||||
it's parsed as an expression that selects the attribute `sh` from the variable `builder`.
|
|
||||||
|
|
||||||
Path literals may also refer to absolute paths by starting with a slash.
|
|
||||||
|
|
||||||
> **Note**
|
|
||||||
>
|
|
||||||
> Absolute paths make expressions less portable.
|
|
||||||
> In the case where a function translates a path literal into an absolute path string for a configuration file, it is recommended to write a string literal instead.
|
|
||||||
> This avoids some confusion about whether files at that location will be used during evaluation.
|
|
||||||
> It also avoids unintentional situations where some function might try to copy everything at the location into the store.
|
|
||||||
|
|
||||||
If the first component of a path is a `~`, it is interpreted such that the rest of the path were relative to the user's home directory.
|
|
||||||
For example, `~/foo` would be equivalent to `/home/edolstra/foo` for a user whose home directory is `/home/edolstra`.
|
|
||||||
Path literals that start with `~` are not allowed in [pure](@docroot@/command-ref/conf-file.md#conf-pure-eval) evaluation.
|
|
||||||
|
|
||||||
Paths can be used in [string interpolation] and string concatenation.
|
|
||||||
For instance, evaluating `"${./foo.txt}"` will cause `foo.txt` from the same directory to be copied into the Nix store and result in the string `"/nix/store/<hash>-foo.txt"`.
|
|
||||||
|
|
||||||
Note that the Nix language assumes that all input files will remain _unchanged_ while evaluating a Nix expression.
|
|
||||||
For example, assume you used a file path in an interpolated string during a `nix repl` session.
|
|
||||||
Later in the same session, after having changed the file contents, evaluating the interpolated string with the file path again might not return a new [store path], since Nix might not re-read the file contents. Use `:r` to reset the repl as needed.
|
|
||||||
|
|
||||||
[store path]: @docroot@/store/store-path.md
|
|
||||||
|
|
||||||
Path literals can also include [string interpolation], besides being [interpolated into other expressions].
|
|
||||||
|
|
||||||
[interpolated into other expressions]: ./string-interpolation.md#interpolated-expressions
|
|
||||||
|
|
||||||
At least one slash (`/`) must appear *before* any interpolated expression for the result to be recognized as a path.
|
|
||||||
|
|
||||||
`a.${foo}/b.${bar}` is a syntactically valid number division operation.
|
|
||||||
`./a.${foo}/b.${bar}` is a path.
|
|
||||||
|
|
||||||
[Lookup path](./constructs/lookup-path.md) literals such as `<nixpkgs>` also resolve to path values.
|
|
||||||
|
|
||||||
- <a id="type-boolean" href="#type-boolean">Boolean</a>
|
|
||||||
|
|
||||||
*Booleans* with values `true` and `false`.
|
|
||||||
|
|
||||||
- <a id="type-null" href="#type-null">Null</a>
|
|
||||||
|
|
||||||
The null value, denoted as `null`.
|
|
||||||
|
|
||||||
## List
|
|
||||||
|
|
||||||
Lists are formed by enclosing a whitespace-separated list of values
|
|
||||||
between square brackets. For example,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
[ 123 ./foo.nix "abc" (f { x = y; }) ]
|
|
||||||
```
|
|
||||||
|
|
||||||
defines a list of four elements, the last being the result of a call to
|
|
||||||
the function `f`. Note that function calls have to be enclosed in
|
|
||||||
parentheses. If they had been omitted, e.g.,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
[ 123 ./foo.nix "abc" f { x = y; } ]
|
|
||||||
```
|
|
||||||
|
|
||||||
the result would be a list of five elements, the fourth one being a
|
|
||||||
function and the fifth being a set.
|
|
||||||
|
|
||||||
Note that lists are only lazy in values, and they are strict in length.
|
|
||||||
|
|
||||||
Elements in a list can be accessed using [`builtins.elemAt`](./builtins.md#builtins-elemAt).
|
|
||||||
|
|
||||||
## Attribute Set
|
|
||||||
|
|
||||||
An attribute set is a collection of name-value-pairs (called *attributes*) enclosed in curly brackets (`{ }`).
|
|
||||||
|
|
||||||
An attribute name can be an identifier or a [string](#string).
|
|
||||||
An identifier must start with a letter (`a-z`, `A-Z`) or underscore (`_`), and can otherwise contain letters (`a-z`, `A-Z`), numbers (`0-9`), underscores (`_`), apostrophes (`'`), or dashes (`-`).
|
|
||||||
|
|
||||||
> **Syntax**
|
|
||||||
>
|
|
||||||
> *name* = *identifier* | *string* \
|
|
||||||
> *identifier* ~ `[a-zA-Z_][a-zA-Z0-9_'-]*`
|
|
||||||
|
|
||||||
Names and values are separated by an equal sign (`=`).
|
|
||||||
Each value is an arbitrary expression terminated by a semicolon (`;`).
|
|
||||||
|
|
||||||
> **Syntax**
|
|
||||||
>
|
|
||||||
> *attrset* = `{` [ *name* `=` *expr* `;` ]... `}`
|
|
||||||
|
|
||||||
Attributes can appear in any order.
|
|
||||||
An attribute name may only occur once.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{
|
|
||||||
x = 123;
|
|
||||||
text = "Hello";
|
|
||||||
y = f { bla = 456; };
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This defines a set with attributes named `x`, `text`, `y`.
|
|
||||||
|
|
||||||
Attributes can be accessed with the [`.` operator](./operators.md#attribute-selection).
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ a = "Foo"; b = "Bar"; }.a
|
|
||||||
```
|
|
||||||
|
|
||||||
This evaluates to `"Foo"`.
|
|
||||||
|
|
||||||
It is possible to provide a default value in an attribute selection using the `or` keyword.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ a = "Foo"; b = "Bar"; }.c or "Xyzzy"
|
|
||||||
```
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ a = "Foo"; b = "Bar"; }.c.d.e.f.g or "Xyzzy"
|
|
||||||
```
|
|
||||||
|
|
||||||
will both evaluate to `"Xyzzy"` because there is no `c` attribute in the set.
|
|
||||||
|
|
||||||
You can use arbitrary double-quoted strings as attribute names:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ "$!@#?" = 123; }."$!@#?"
|
|
||||||
```
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let bar = "bar"; in
|
|
||||||
{ "foo ${bar}" = 123; }."foo ${bar}"
|
|
||||||
```
|
|
||||||
|
|
||||||
Both will evaluate to `123`.
|
|
||||||
|
|
||||||
Attribute names support [string interpolation]:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let bar = "foo"; in
|
|
||||||
{ foo = 123; }.${bar}
|
|
||||||
```
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let bar = "foo"; in
|
|
||||||
{ ${bar} = 123; }.foo
|
|
||||||
```
|
|
||||||
|
|
||||||
Both will evaluate to `123`.
|
|
||||||
|
|
||||||
In the special case where an attribute name inside of a set declaration
|
|
||||||
evaluates to `null` (which is normally an error, as `null` cannot be coerced to
|
|
||||||
a string), that attribute is simply not added to the set:
|
|
||||||
|
|
||||||
```nix
|
|
||||||
{ ${if foo then "bar" else null} = true; }
|
|
||||||
```
|
|
||||||
|
|
||||||
This will evaluate to `{}` if `foo` evaluates to `false`.
|
|
||||||
|
|
||||||
A set that has a `__functor` attribute whose value is callable (i.e. is
|
|
||||||
itself a function or a set with a `__functor` attribute whose value is
|
|
||||||
callable) can be applied as if it were a function, with the set itself
|
|
||||||
passed in first , e.g.,
|
|
||||||
|
|
||||||
```nix
|
|
||||||
let add = { __functor = self: x: x + self.x; };
|
|
||||||
inc = add // { x = 1; };
|
|
||||||
in inc 1
|
|
||||||
```
|
|
||||||
|
|
||||||
evaluates to `2`. This can be used to attach metadata to a function
|
|
||||||
without the caller needing to treat it specially, or to implement a form
|
|
||||||
of object-oriented programming, for example.
|
|
|
@ -74,7 +74,7 @@ MixEvalArgs::MixEvalArgs()
|
||||||
.description = R"(
|
.description = R"(
|
||||||
Add *path* to the Nix search path. The Nix search path is
|
Add *path* to the Nix search path. The Nix search path is
|
||||||
initialized from the colon-separated [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH) environment
|
initialized from the colon-separated [`NIX_PATH`](@docroot@/command-ref/env-common.md#env-NIX_PATH) environment
|
||||||
variable, and is used to look up the location of Nix expressions using [paths](@docroot@/language/values.md#type-path) enclosed in angle
|
variable, and is used to look up the location of Nix expressions using [paths](@docroot@/language/types.md#type-path) enclosed in angle
|
||||||
brackets (i.e., `<nixpkgs>`).
|
brackets (i.e., `<nixpkgs>`).
|
||||||
|
|
||||||
For instance, passing
|
For instance, passing
|
||||||
|
|
|
@ -732,11 +732,12 @@ static RegisterPrimOp primop_genericClosure(PrimOp {
|
||||||
Each attribute set in the list `startSet` and the list returned by `operator` must have an attribute `key`, which must support equality comparison.
|
Each attribute set in the list `startSet` and the list returned by `operator` must have an attribute `key`, which must support equality comparison.
|
||||||
The value of `key` can be one of the following types:
|
The value of `key` can be one of the following types:
|
||||||
|
|
||||||
- [Number](@docroot@/language/values.md#type-number)
|
- [Int](@docroot@/language/types.md#type-int)
|
||||||
- [Boolean](@docroot@/language/values.md#type-boolean)
|
- [Float](@docroot@/language/types.md#type-float)
|
||||||
- [String](@docroot@/language/values.md#type-string)
|
- [Boolean](@docroot@/language/types.md#type-boolean)
|
||||||
- [Path](@docroot@/language/values.md#type-path)
|
- [String](@docroot@/language/types.md#type-string)
|
||||||
- [List](@docroot@/language/values.md#list)
|
- [Path](@docroot@/language/types.md#type-path)
|
||||||
|
- [List](@docroot@/language/types.md#list)
|
||||||
|
|
||||||
The result is produced by calling the `operator` on each `item` that has not been called yet, including newly added items, until no new items are added.
|
The result is produced by calling the `operator` on each `item` that has not been called yet, including newly added items, until no new items are added.
|
||||||
Items are compared by their `key` attribute.
|
Items are compared by their `key` attribute.
|
||||||
|
@ -1709,7 +1710,7 @@ static RegisterPrimOp primop_baseNameOf({
|
||||||
.name = "baseNameOf",
|
.name = "baseNameOf",
|
||||||
.args = {"x"},
|
.args = {"x"},
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
Return the *base name* of either a [path value](@docroot@/language/values.md#type-path) *x* or a string *x*, depending on which type is passed, and according to the following rules.
|
Return the *base name* of either a [path value](@docroot@/language/types.md#type-path) *x* or a string *x*, depending on which type is passed, and according to the following rules.
|
||||||
|
|
||||||
For a path value, the *base name* is considered to be the part of the path after the last directory separator, including any file extensions.
|
For a path value, the *base name* is considered to be the part of the path after the last directory separator, including any file extensions.
|
||||||
This is the simple case, as path values don't have trailing slashes.
|
This is the simple case, as path values don't have trailing slashes.
|
||||||
|
@ -1843,7 +1844,7 @@ static RegisterPrimOp primop_findFile(PrimOp {
|
||||||
.doc = R"(
|
.doc = R"(
|
||||||
Find *lookup-path* in *search-path*.
|
Find *lookup-path* in *search-path*.
|
||||||
|
|
||||||
A search path is represented list of [attribute sets](./values.md#attribute-set) with two attributes:
|
A search path is represented list of [attribute sets](./types.md#attribute-set) with two attributes:
|
||||||
- `prefix` is a relative path.
|
- `prefix` is a relative path.
|
||||||
- `path` denotes a file system location
|
- `path` denotes a file system location
|
||||||
The exact syntax depends on the command line interface.
|
The exact syntax depends on the command line interface.
|
||||||
|
@ -1864,7 +1865,7 @@ static RegisterPrimOp primop_findFile(PrimOp {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The lookup algorithm checks each entry until a match is found, returning a [path value](@docroot@/language/values.html#type-path) of the match:
|
The lookup algorithm checks each entry until a match is found, returning a [path value](@docroot@/language/types.md#type-path) of the match:
|
||||||
|
|
||||||
- If *lookup-path* matches `prefix`, then the remainder of *lookup-path* (the "suffix") is searched for within the directory denoted by `path`.
|
- If *lookup-path* matches `prefix`, then the remainder of *lookup-path* (the "suffix") is searched for within the directory denoted by `path`.
|
||||||
Note that the `path` may need to be downloaded at this point to look inside.
|
Note that the `path` may need to be downloaded at this point to look inside.
|
||||||
|
@ -2292,7 +2293,7 @@ static RegisterPrimOp primop_toFile({
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that `${configFile}` is a
|
Note that `${configFile}` is a
|
||||||
[string interpolation](@docroot@/language/values.md#type-string), so the result of the
|
[string interpolation](@docroot@/language/types.md#type-string), so the result of the
|
||||||
expression `configFile`
|
expression `configFile`
|
||||||
(i.e., a path like `/nix/store/m7p7jfny445k...-foo.conf`) will be
|
(i.e., a path like `/nix/store/m7p7jfny445k...-foo.conf`) will be
|
||||||
spliced into the resulting string.
|
spliced into the resulting string.
|
||||||
|
@ -4538,7 +4539,7 @@ void EvalState::createBaseEnv()
|
||||||
It can be returned by
|
It can be returned by
|
||||||
[comparison operators](@docroot@/language/operators.md#Comparison)
|
[comparison operators](@docroot@/language/operators.md#Comparison)
|
||||||
and used in
|
and used in
|
||||||
[conditional expressions](@docroot@/language/constructs.md#Conditionals).
|
[conditional expressions](@docroot@/language/syntax.md#Conditionals).
|
||||||
|
|
||||||
The name `true` is not special, and can be shadowed:
|
The name `true` is not special, and can be shadowed:
|
||||||
|
|
||||||
|
@ -4558,7 +4559,7 @@ void EvalState::createBaseEnv()
|
||||||
It can be returned by
|
It can be returned by
|
||||||
[comparison operators](@docroot@/language/operators.md#Comparison)
|
[comparison operators](@docroot@/language/operators.md#Comparison)
|
||||||
and used in
|
and used in
|
||||||
[conditional expressions](@docroot@/language/constructs.md#Conditionals).
|
[conditional expressions](@docroot@/language/syntax.md#Conditionals).
|
||||||
|
|
||||||
The name `false` is not special, and can be shadowed:
|
The name `false` is not special, and can be shadowed:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue