aboutsummaryrefslogtreecommitdiff
path: root/doc/manual
diff options
context:
space:
mode:
authorValentin Gagarin <valentin.gagarin@tweag.io>2023-05-11 19:23:13 +0200
committerValentin Gagarin <valentin.gagarin@tweag.io>2023-05-17 13:41:34 +0200
commitd8bfeda1643f434ae015caa4f59d9f4b7f4270d7 (patch)
treef0c34951763211258ed1fc7ae2c57b59d52df519 /doc/manual
parentdfc393ffd3cb38c60146199c60f03b7e1d97aec8 (diff)
document identifier syntax for attribute sets
it's more likely for readers to find it right there. this also slightly rewords examples to make them stand out better. in the long run there probably needs to be a dedicated section on formal syntax, and better highlighting of examples.
Diffstat (limited to 'doc/manual')
-rw-r--r--doc/manual/src/language/constructs.md47
-rw-r--r--doc/manual/src/language/operators.md11
-rw-r--r--doc/manual/src/language/values.md20
3 files changed, 52 insertions, 26 deletions
diff --git a/doc/manual/src/language/constructs.md b/doc/manual/src/language/constructs.md
index 1c01f2cc7..c53eb8889 100644
--- a/doc/manual/src/language/constructs.md
+++ b/doc/manual/src/language/constructs.md
@@ -2,8 +2,11 @@
## Recursive sets
-Recursive sets are just normal sets, but the attributes can refer to
-each other. For example,
+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 {
@@ -12,7 +15,9 @@ rec {
}.x
```
-evaluates to `123`. Note that without `rec` the binding `x = y;` would
+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
@@ -33,7 +38,10 @@ will crash with an `infinite recursion encountered` error message.
## Let-expressions
A let-expression allows you to define local variables for an expression.
-For instance,
+
+> *let-in* = `let` [ *identifier* = *expr* ]... `in` *expr*
+
+Example:
```nix
let
@@ -42,18 +50,19 @@ let
in x + y
```
-evaluates to `"foobar"`.
+This evaluates to `"foobar"`.
## Inheriting attributes
-When defining a set or in a let-expression 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. For instance,
+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;
+{
+ inherit x;
y = 456;
}
```
@@ -62,15 +71,23 @@ is equivalent to
```nix
let x = 123; in
-{ x = x;
+{
+ x = x;
y = 456;
}
```
-and both evaluate to `{ x = 123; y = 456; }`. (Note that this works
-because `x` is added to the lexical scope by the `let` construct.) It is
-also possible to inherit attributes from another set. For instance, in
-this fragment from `all-packages.nix`,
+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) {
diff --git a/doc/manual/src/language/operators.md b/doc/manual/src/language/operators.md
index 3e929724d..f8382ae19 100644
--- a/doc/manual/src/language/operators.md
+++ b/doc/manual/src/language/operators.md
@@ -35,17 +35,14 @@
## Attribute selection
+> *attrset* `.` *attrpath* \[ `or` *expr* \]
+
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.
-<!-- FIXME: the following should to into its own language syntax section, but that needs more work to fit in well -->
-
-An attribute path is a dot-separated list of attribute names.
-An attribute name can be an identifier or a string.
+An attribute path is a dot-separated list of [attribute names](./values.md#attribute-set).
-> *attrpath* = *name* [ `.` *name* ]... \
-> *name* = *identifier* | *string* \
-> *identifier* ~ `[a-zA-Z_][a-zA-Z0-9_'-]*`
+> *attrpath* = *name* [ `.` *name* ]...
[Attribute selection]: #attribute-selection
diff --git a/doc/manual/src/language/values.md b/doc/manual/src/language/values.md
index 9d0301753..2ae3e143a 100644
--- a/doc/manual/src/language/values.md
+++ b/doc/manual/src/language/values.md
@@ -164,9 +164,17 @@ Note that lists are only lazy in values, and they are strict in length.
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 (`-`).
+
+> *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 (`;`).
+> *attrset* = `{` [ *name* `=` *expr* `;` `]`... `}`
+
Attributes can appear in any order.
An attribute name may only occur once.
@@ -182,15 +190,19 @@ Example:
This defines a set with attributes named `x`, `text`, `y`.
-Attributes can be selected from a set using the `.` operator. For
-instance,
+Attributes can be accessed with the [`.` operator](./operators.md#attribute-selection).
+
+Example:
```nix
{ a = "Foo"; b = "Bar"; }.a
```
-evaluates to `"Foo"`. It is possible to provide a default value in an
-attribute selection using the `or` keyword:
+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"