Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve the documentation of lib.extends and how it relates to overlays #248220

Merged
merged 4 commits into from
Jan 12, 2024

Conversation

infinisil
Copy link
Member

Description of changes

lib.extends is the part of Nixpkgs that actually implements how overlays work, but its documentation was rather poor. This is an attempt to improve it.

This also relates to @roberth's suggested improvements to the lib.fix documentation in #242318 and @amjoseph-nixpkgs's suggested improvements to the extends documentation in #245825.

Things done

  • Built the documentation and checked that it looks alright.

The previous one was unnecessarily confusing.
- Better names:
  - self -> final
  - super -> prev
  - rattrs -> f
  - f -> overlay
- Add documentation to the function arguments
- Add some spacing
@infinisil infinisil requested a review from roberth August 9, 2023 22:27
@infinisil infinisil requested a review from a user August 9, 2023 22:27
@github-actions github-actions bot added the 6.topic: lib The Nixpkgs function library label Aug 9, 2023
@infinisil infinisil mentioned this pull request Aug 13, 2023
12 tasks
@@ -53,42 +53,96 @@ rec {
else converge f x';

/*
Modify the contents of an explicitly recursive attribute set in a way that
honors `self`-references. This is accomplished with a function
`extends overlay f` applies the overlay `overlay` to the fixed-point function `f` to get a new fixed-point function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Fixed point function" is hard to define and would be a confusing term. I think we can avoid introducing this term.

Suggested change
`extends overlay f` applies the overlay `overlay` to the fixed-point function `f` to get a new fixed-point function.
Apply an overlay.
Consider `extends overlay f`, where `f` is a function that's suitable for passing to `fix`.
Instead of tying the fixed-point, `extends` returns a modification of `f` with the `overlay` applied.
This means that the "self" parameter of `f` will not refer to `f`'s return value, but rather to the value after applying the overlay.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Fixable function" would be more accurate, but still not helpful.
"Endomorphism" would be hilarious ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`extends overlay f` applies the overlay `overlay` to the fixed-point function `f` to get a new fixed-point function.
Apply an overlay to a fixed-point function.

The entire example is expanded with more structure below.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's very good to mention extends overlay f in the beginning, so one can immediately know the order of arguments. I've seen complaints about this being unclear before.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apply an overlay to a fixed-point function.

This is too much and too vague for no reason.
There's really only one way we can "apply" an overlay, and we have to explain what kind of function that is anyway.
"Fixed-point function" sounds nice, and we might have some intuition about what that might be, but this is completely idiosyncratic to Nixers, which makes it bad for an introduction.
In fact it could be defined in either of two ways

  • Just fix
  • A function that has a fixed-point, which would be wrong here! The fixed point of f is completely irrelevant, if it even exists, because we won't be taking it. Instead we may take the fixed-point of the composition of f with an overlay, but extends isn't even doing that.

Now this does remind me that "apply" may be the wrong term for this composition. The "application" of a fixed point happens in fix, or "by" fix if that's acceptable language.
I don't think "compose" is appropriate either, because composition generally refers to objects of some kind of same-ish type, such as two or more functions, two or more modules, etc. Not operands that need distinct terms for a description.

An accurate introductory description would be "Extend a function by means of an overlay". This is close to @infinisil's original introduction, but without the code. "Use an overlay to extend a function" if we care about argument order in the intro.

I also think it's good to address that f might be thought of as possibly having a fixed point, but that it won't be used that way.

Suggested change
`extends overlay f` applies the overlay `overlay` to the fixed-point function `f` to get a new fixed-point function.
Extend a function using an overlay.
Consider the context of an `extend` invocation to be:
```nix
let f = self: ...;
in extends overlay f
```
Instead of tying the fixed-point of `f`, `extends` returns a composition of `f` with the `overlay` applied.
This means that the `self` parameter of `f` will not refer to `f`'s return value, but rather to the value after applying the overlay.

Maybe we could cut down a bit on the meta language

Suggested change
`extends overlay f` applies the overlay `overlay` to the fixed-point function `f` to get a new fixed-point function.
Extend a function using an overlay.
Consider
```nix
let f = self: ...;
in extends overlay f
```
Instead of tying the fixed-point of `f`, `extends` returns a composition of `f` with the `overlay` applied.
This means that the `self` parameter of `f` will not refer to `f`'s return value, but rather to the value after applying the overlay.

("with the overlay applied", "applying the overlay" are valid here because it refers to the overlay as a (curried) function. It would not be valid as a description of the extends interface. Overexplaining for the purpose of our discussion only)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that the descriptive language says much about what's happening - at least not to me - while the later examples explain a lot. It's fine if we say "extend a function with an overlay" if the fixed point aspect doesn't matter, and it's fine to show a brief example for argument order, but then it should also contain a sample overlay.

But still I think it would be enough just to skip that and go right to the next part.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but then it should also contain a sample overlay.

I've assumed that the overlay "type" is described elsewhere. That was probably wrong (?) and we should have a separate section explaining what an overlay is, because most people who need to know about overlays just need to write and understand them, but don't need to call extends.

We can leave out those details here because exactly how it's wired just follows from the definition of an overlay, and we don't have to refer to the parameters here. (Although maybe it's worth describing some equalities, but then that could all be done in its own section. This amount of detail is just not necessary at the start of the description; as you can see almost everything can be said with just f, overlay and self.)

enough just to skip that and go right to the next part.

Not sure what you mean. Skip introducing names, and assume people read the source? The source doesn't come with these docs as they are extracted, so we can't do that, and nor should we.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean. Skip introducing names, and assume people read the source?

No, skip the two lines I suggested to leave out. We don't have to define overlays here, just do the same type of sketch you suggested as for the fixed point function.

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2023-08-17-documentation-team-meeting-notes-73/31853/1

@roberth roberth self-assigned this Aug 19, 2023

```nix
g = self: super: { foo = super.foo + " + "; }
A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument, only possible due to Nix's lazy evaluation.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument, only possible due to Nix's lazy evaluation.
A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument.
This is possible due to Nix's lazy evaluation.

Co-Authored-By: Valentin Gagarin <valentin.gagarin@tweag.io>
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2023-09-28-documentation-team-meeting-notes-83/33599/1


where `prev` refers to the result of the original function to `final`, and `final` is the result of the composition of the overlay and the original function.

Applying an overlay is done with `extends`:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be easier to read out of context of this file if we say lib.extends instead of extends:

Suggested change
Applying an overlay is done with `extends`:
Applying an overlay is done with `lib.extends`:

(here and in the rest of the comment)

The same way you're mentioning lib.fix below instead of just fix (although you're using fix not lib.fix in the code example..)

I'd suggest to also change the code examples to mention lib. for better readability, wdyt?

@infinisil
Copy link
Member Author

I don't really have the time to work on this, but this has lingered for too long and is good enough. The docs are better than before and that's what matters most, so I'll just make the executive decision to merge this right now (thanks @9999years for the push!). If anybody thinks it should be improved still, please make a follow-up PR

@infinisil infinisil merged commit 501963a into NixOS:master Jan 12, 2024
20 checks passed
@infinisil infinisil deleted the document-extends branch January 12, 2024 01:25
@asymmetric asymmetric added the 6.topic: documentation Meta-discussion about documentation and its workflow label Jan 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6.topic: documentation Meta-discussion about documentation and its workflow 6.topic: lib The Nixpkgs function library 10.rebuild-darwin: 0 10.rebuild-linux: 1-10 12.approvals: 1
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

7 participants