Hi,
I’d like to propose a solution to one of the “papercut” problems we have, with the ?
operator.
By formatting it differently, we can nudge readers in the right direction.
I think we have good reasons to make this change, and for this reason I would kind of expect it to be an uncontroversial and a fairly quick RFC.
What do you think?
UPDATE:
I’ve overlooked the fact that ?
does not have .
's precedence, which I consider to be a fatal flaw for the proposal as written.
We might look at introducing a new operator to fix this.
Something to keep in mind when reading the proposal
Summary
Visually differentiate the “has attribute” symbol from the “parameter default” symbol in Nixpkgs.
Motivation
The Nix language syntax has a ?
symbol, which is used in two places in the grammar.
- The “has attribute” operator, and
- The symbol that precedes a default value for an attribute set destructuring binding.
This proposal focuses on the way we format the prior in Nixpkgs, for two reasons
- It is unfortunate that
?
has two distinct meanings. Visually differentiating them helps slightly with learning and understanding. - Despite syntactically being a binary operator,
?
does not behave like the other binary operators, which causes confusion.
The ?
operator behaves a lot like the .
operator (attribute lookup or “selection”), so it would make sense to format the use of these operators the same.
So by changing the formatting convention of ?
, we expect a slight improvement in learning and understanding of the Nix language.
Detailed design
Change all documentation and style guides within the NixOS projects (nix, nixpkgs, etc), to require that
- The “has attribute” operator is formatted without any whitespace before or after the
?
character. - The default value declaration for bindings introduced in attribute set destructuring function declarations is formatted with a single space on both sides of the
?
character.
Furthermore we encourage all Nix expression formatting tools to adopt these rules. A tool that supports vertical alignment may generalize “single space” to “at least one space”, but note that this is not an endorsement of vertical formatting.
Examples and Interactions
End result
As a result of this RFC, checking for an attribute should look as follows:
f = drv:
if drv?passthru
then drv.passthru
else { };
You can see the similarity with the .
operator, and you would be right to assume that passthru
is a literal in both cases, as opposed to a variable reference.
A equivalent function declaration using a default still looks as follows:
f = { passthru ? { } , ... }: passthru;
Interlude about .
or
ternary operator
Although f
is based on real Nixpkgs code and it is a nicely simple example, it is worth noting that f
can be further simplified to
f = drv: drv.passthru or {}
However, this solution does not generalize to all problems that involve checking whether an attribute exists, so we will ignore it for the purpose of this RFC.
Source of confusion
As discussed, a potential source of confusion is between the two meanings of ?
. However, while they look the same, they can be disambiguated by their context; where they occur.
The same does not apply to the other source of confusion, as was encountered in nix#1059.
Given that almost all operators take expressions, except the “obvious” exception, .
, we would expect the following to generalization to work:
- The operator
+
ina + b
operates in the expressionsa
andb
. - The operator
//
ina // b
operates in the expressionsa
andb
. - The operator
?
ina ? b
operates in the expressionsa
andb
, except it does not.b
is an identifier and not an expression.
While removing the whitespace around ?
, resulting in a?b
does not clearly convey this fact, it may at least raise attention.
Drawbacks
Contributors to Nixpkgs will have to adapt a bit, and they may have to be reminded of the new convention.
Alternatives
Change the language
The current proposal makes for a slight improvement in readability and learning, but a more complete effect could be achieved by changing the language.
The downside of this is that it is a more invasive change, that takes much more effort to decide and implement, and involves a long wait before Nixpkgs can transition to it.
Specifically, RFC 137 Nix language versioning needs to be implemented first, and the whole community needs to upgrade to a new Nix version that implements the change. Furthermore language changes have a significant cost.
To illustrate what could be considered in an RFC that changes the syntax, we might create a less ambiguous syntax such as
f = { passthru or {}, ... }: passthru;
and
f = drv: drv.?passthru;
However, for the reasons stated above, we won’t explore such proposals in this RFC.
Always format with spaces
The current de facto rule is to always use spaces around ?
.
While ignoring the semantics makes for simple rules, it does not aid understanding.
This alternative has the benefit of requiring no action.
However, if the minor nature of the improvement in this RFC leads some to believe that it is not worthwhile, I would suggest that they focus on more important things while they let the change happen.
Prior art
As of writing, I am unaware of prior discussions of this ambiguity, except for nix#1059.
?
is hard to search for, so if anyone remembers a prior discussion, a link would be highly appreciated.
- Issue nix#1059: “? operator gives wrong results”
- The
?
operator was introduced before Nix 0.5 and has been documented with spaces since.
Unresolved questions
No unresolved questions as of yet.
Future work
- Consider changing the language to support a more consistent and unambiguous syntax. An example of this was shown for illustrative purposes in the Alternatives section.
The part with the uninteresting metadata
This goes at the top of the RFC, but isn’t rendered in a readable manner by discourse; hence the “code” formatting.
---
feature: quest_to_questionably_solve_the_question_about_question_mark
start-date: (fill me in with today's date, YYYY-MM-DD)
author: Robert Hensing
co-authors: (find a buddy later to help out with the RFC)
shepherd-team: (names, to be nominated and accepted by RFC steering committee)
shepherd-leader: (name to be appointed by RFC steering committee)
related-issues: https://github.com/NixOS/nix/issues/1059
---