-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: add variables and identifiers; rework scope
- Loading branch information
Showing
3 changed files
with
73 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Variables and Identifiers | ||
|
||
> **Grammar** | ||
> | ||
> `word` → `[A-Z_a-z]['\-0-9A-Z_a-z]*` | ||
> | ||
> `identifier` → `word` (excluding keywords) | ||
> | ||
> `expr` → `identifier` | ||
An _identifier_ is a sequence of characters starting with an ASCII letter or an underscore, followed by any number of ASCII letters, digits, underscores, apostrophes, or hyphens. | ||
|
||
A _variable_ is an identifier used as an expression, if the identifier is not one of the following _keywords_: | ||
|
||
- [`assert`][assert] | ||
- [`else`][if] | ||
- [`if`][if] | ||
- [`in`][let] | ||
- [`inherit`][inherit] | ||
- [`let`][let] | ||
- [`or`][or] _(see note)_ | ||
- [`rec`][rec] | ||
- [`then`][if] | ||
- [`with`][with] | ||
|
||
[assert]: syntax.md#assertions | ||
[if]: syntax.md#conditionals | ||
[let]: syntax.md#let-expressions | ||
[inherit]: syntax.md#inheriting-attributes | ||
[or]: operators.md#attribute-selection | ||
[rec]: syntax.md#recursive-sets | ||
[with]: syntax.md#with-expressions | ||
|
||
A variable must have the same name as a definition in the [scope] that encloses it. | ||
The value of a variable is the value of the corresponding expression in the enclosing scope. | ||
|
||
> **Note** | ||
> | ||
> The Nix interpreter currently allows `or` to be used as a variable in some contexts, for backwards compatibility reasons. | ||
> Users are advised not to rely on this, as there are long-standing issues with how `or` as a variable is parsed, which can't be resolved without making a breaking change to the language. | ||
[scope]: scope.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,34 @@ | ||
# Scoping rules | ||
|
||
Nix is [statically scoped](https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope), but with multiple scopes and shadowing rules. | ||
A _scope_ in the Nix language is an [identifier]-keyed dictionary, mapping each identifier to an expression and a _definition type_. | ||
The definition type is either _explicit_ or _implicit_. | ||
Each entry in this dictionary is a _definition_. | ||
|
||
* primary scope: explicitly-bound variables | ||
* [`let`](./syntax.md#let-expressions) | ||
* [`inherit`](./syntax.md#inheriting-attributes) | ||
* [function](./syntax.md#functions) arguments | ||
[identifier]: identifiers.md | ||
|
||
* secondary scope: implicitly-bound variables | ||
* [`with`](./syntax.md#with-expressions) | ||
Explicit definitions are created by the following expressions: | ||
* [let-expressions](syntax.md#let-expressions) | ||
* [recursive attribute set literals](syntax.md#recursive-sets) (`rec`) | ||
* [function literals](syntax.md#functions) | ||
|
||
Primary scope takes precedence over secondary scope. | ||
See [`with`](./syntax.md#with-expressions) for a detailed example. | ||
Implicit definitions are only created by [with-expressions]. | ||
|
||
[with-expressions]: syntax.md#with-expressions | ||
|
||
Each of the above expressions defines which of its subexpressions are _enclosed_ by the extended scope. | ||
The outermost expression of a Nix language file is enclosed by the [global scope], which contains only explicit definitions. | ||
Nix is [statically scoped]; the enclosing scope of an expression is always determined only by the expressions that contain it as a subexpression, and not by the context in which it is evaluated. | ||
|
||
[global scope]: builtins.md | ||
[statically scoped]: https://en.wikipedia.org/wiki/Scope_(computer_science)#Lexical_scope | ||
|
||
The above expressions _extend_ their enclosing scope by adding new definitions, or replacing existing ones with the same name. | ||
An explicit definition can replace a definition of any type; an implicit definition can only replace another implicit definition. | ||
See [with-expressions] for a detailed example. | ||
|
||
> **Note** | ||
> | ||
> Expressions entered into the [Nix REPL] are enclosed by a scope that can be extended by command line arguments or previous REPL commands. | ||
> These ways of extending scope are not, strictly speaking, part of the Nix language. | ||
[Nix REPL]: @docroot@/command-ref/new-cli/nix3-repl.md |