---
feature: inherit-as-list
start-date: 2021-10-17
author: Ryan Burns (@r-burns)
co-authors: (find a buddy later to help out with the RFC)
shepherd-team: @synthetica9, @infinisil, @kevincox, @bobvanderlinden
shepherd-leader: @kevincox
related-issues: (will contain links to implementation PRs)
---
This RFC proposes a new Nix syntax <attrset>.[ <attrnames> ]
,
which constructs a list from the values of an attrset.
The goal is to provide a similarly-terse but more principled alternative
to the often-used with <attrset>; [ <attrnames> ]
.
It is currently cumbersome to create a list from the values of an attrset.
If one has an attrset attrs
and wishes to create a list containing some of
its values, one could naively write:
[ attrs.a attrs.b attrs.c ]
To avoid typing attrs
many times, one will typically use with
instead:
with attrs; [ a b c ]
However, the with
expression has many well-known drawbacks, such as
unintuitive shadowing behavior [1][2], prevention of static scope checking [3][4],
and reduced evaluation performance [3].
- [1] NixOS/nix#490
- [2] NixOS/nix#1361
- [3] NixOS/nixpkgs#101139
- [4] https://nix.dev/recipes/best-practices#with-scopes
Nonetheless, Nix expression authors are subtly guided toward the with
form
because it is (or at least appears) simpler than any existing alternatives.
Some alternatives are suggested in
https://nix.dev/recipes/best-practices#with-scopes, but as these
are more verbose and complex than with
, they are rarely used.
The goal of this RFC is to provide a similarly-terse alternative which avoids these drawbacks.
The proposed syntax is:
attrs.[ a b c ]
This expression is syntactic sugar for:
[ attrs.a attrs.b attrs.c ]
As the token .
immediately preceding [
is currently a syntax error,
a Nix interpreter which supports this new language feature will be compatible
with existing Nix code.
This RFC is implemented here: NixOS/nix#5402
For MVP functionality, only minor additions to src/libexpr/parser.y
are
needed. If accepted, the changes to the Nix interpreter can be backported
to current releases if desired. Relevant language documentation and
third-party parsers/linters would also need to be updated.
This would be useful for many languages and frameworks in Nixpkgs which extract packages from a package set argument.
For example, python3.withPackages (ps: ps.[ ... ])
will serve as a
more fine-grained alternative to python3.withPackages (ps: with ps; [ ... ])
.
This would apply similarly to vim.withPlugins
, lua.withPackages
, etc.
Certain list-typed meta
fields could also make use of this feature, e.g.:
meta.licenses = lib.licenses.[ bsd3 mit ];
meta.maintainers = lib.maintainers.[ johndoe janedoe ];
Note that only simple textual attrnames are allowed in the square brackets.
For example, pkgs.[ (openssl.overrideAttrs { patches = [ ... ]; }) ]
is currently a syntax error, as is pkgs.[ "${some_expression}" ]
,
a.[ b.[ c d ] ]
, and a.[ [ b c ] [ d e ] ]
.
Future RFCs may add additional support for useful idioms such as
pkgs.[ python310 python310Packages.pytorch ]
on a case-by-case basis,
but that is not planned for this RFC.
For a comparison of other forms of syntax considered but not proposed in this RFC, refer to the Alternatives section.
- This will add complexity to the Nix grammar and any third-party tools which operate on Nix expressions.
- Expressions reliant on the new syntax will be incompatible with Nix versions prior to the introduction of this feature.
A number of alternatives have been considered, which can be roughly divided into syntactic (introducing new syntax which requires changes to the Nix language to parse) and non-syntactic.
Priority is given to syntax which would be "backwards compatible" with existing Nix code, meaning that any existing code would be evaluated the same under an interpreter supporting the new syntax. Conversely, evaluating new code under an old interpreter which does not support the new syntax would cause a syntax error.
Some common threads here are the desire to introduce a syntax form which
is simpler and more ergonomic than existing with
or alternatives,
naturally guiding users toward a "safer" form. We also desire consistency,
reusing keywords or syntax patterns but only where it would be
harmonious with the existing Nix language.
Other alternatives have been proposed where the motivation for with
deprecation is acknowledged, but would be resolved without introducing
new syntax to the Nix language.
Alternative | Notes | Cons |
---|---|---|
builtins.attrValues { inherit (attrs) a b c; } |
Considered in initial draft | Verbose, cumbersome to compose, not order-preserving |
select [ "a" "b" "c" ] attrs |
Proposed by ocharles | "highlights wrong (strings are not data but literal variable names)" -7c6f434c " with is slightly more ergonomic", "the proposed change is arguably same [...] but without semantical gotchas" -7c6f434c |
Deprecation of list-types in NixOS modules and build inputs | Proposed by infinisil | "order of buildInputs is significant so unordered sets cannot be used" -jtojnar |
How would this feature be adopted, if accepted?
Determine best practices regarding when this language construct should be used