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

Document what Nix *is* #6420

Merged
merged 124 commits into from
Aug 4, 2022
Merged

Conversation

Ericson2314
Copy link
Member

This is "tracking PR" of a community effort to better document what Nix is.

Per the excellent quadrant in https://documentation.divio.com/ (which we should officially adopt to help organize our docs!) this chapter is firstly reference, and secondly explanation.

It is in a permanent draft state, and this branch contains the "overall plan", with many sections mere outlines yet to be filled out.
As self-sufficient parts are finished off, they will be broken off into individual PRs to be merged sooner.

Currently, this is a collaboration between myself and @fricklerhandwerk, but more contributors are strongly encouraged to help out!

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Apr 20, 2022

I have the impression we should think about how to deal with terminology in general.

One example I already got stuck with is how we introduce what Nix calls "derivation". Since we go from the top level, we correctly call them very generally: "build plan". Build Systems à la Carte sec. 3.2 calls it "task". "(build) recipe" is another term that is currently in the draft.

Still have no idea how to approach this to introduce readers into existing jargon. I would like not just to define "derivation" but make clear that it is a custom term for a concept other systems use as well under a different name.

There is the glossary in the Nix manual, and that would probably a good point to improve upon while at it.

@toraritte
Copy link
Contributor

toraritte commented Apr 20, 2022

One example I already got stuck with is how we introduce what Nix calls "derivation".

This is a great point; I have been using Nix for years and still struggle defining it, even though the gist of it is simple. For me, the difficulty understanding it comes from the way the term has been used in the PhD thesis, the manuals, on the forum, in blog posts, etc.

The concept

There is the concept of "derivation",

  • a component build action, which derives the component from its inputs
    (PhD thesis, page 27, callout 3)

  • the store derivations describe build actions from source
    (PhD thesis, page 42, paragraph 3)

These are high-level descriptions and easy to grasp, but to go further from here, one has to have knowledge about the Nix expression language which has a derivation primop so it can become a circular problem.

Therefore, I think the most important thing is that once a concept/term is introduced, it should be used consistently in the entire document, even if it means increased verbosity. E.g., using "derivation" instead of "Nix derivation expression" is shorter, but misleading (see next section). Also, definitions should be easy to find; a glossary with non-contradicting entries is a good start, and pointing to definitions in the text where they were first introduced would also be helpful by providing more context.

Usage

The confusing part comes from how the term "derivation" is used, as it seemingly means different things depending on context:

  • An attribute set
    The derivation primop (called directly or indirectly) returns the input attribute set, enriched with extra attributes (such as outPath, drvPath, type ... and what else?). People mentioning to "import derivation" used to perplex me because for some reason I was missing this part.

  • Nix derivation expressions
    Nix expressions that eventually call the derivation primop, compared to utility Nix expressions, such as (almost all) functions in builtins. (So every Nix derivation expression is a Nix expression, but not vice versa.)

  • store derivations
    That is, the drv files in /nix/store.

Nix derivation expressions vs. store derivations

This distinction is clearly pointed out in the thesis (emphases mine):

In any case, these derivation Nix expressions are subsequently translated to store derivations
(PhD thesis, page 100, section "5.4. Translating Nix expressions to store derivations", paragraph 2)

Both describe build actions whose result will end up in the Nix store but

  • a Nix derivation expression is a Nix expression whose

    normal form should be a call to derivation, or a nested structure of lists and attribute sets that contain calls to derivation.
    (PhD thesis, page 100, section "5.4. Translating Nix expressions to store derivations", paragraph 2)

    where normal form is defined in 4.3.4. Evaluation rules.

  • a store derivation "encodes a single, specific, constant build action" "with all variability removed" and it is the result of a successful translation of a Nix derivation expression.

    Nix [derivation] expressions can express variability, store derivations cannot.
    (PhD thesis, page 100, section "5.4. Translating Nix expressions to store derivations", paragraph 1)

artifact representation location output variability output file extension
Nix derivation expression Nix expression language somewhere in the file system yes a store derivation .nix (usually)
store derivation ATerms Nix store no the build result (of the instructions) .drv

For example, to demonstrate the output variability in the case of Vim:

image


I think the PhD thesis is fairly underappreciated and more parts should be used from it, even though "derivation" is used ambiguously. Some examples of explanations that I found helpful and also a couple that show why the usage can be confusing (emphases mine, and the square brackets are also added by me):

  • Figure 2.12:

    image
    (PhD thesis, page 39)

    (Where it should say "Nix derivation expression" in the first bubble.)

  • Nix [derivation] expressions are not built directly; rather, they are translated to the more primitive language of store derivations, which encode single component build actions.
    (PhD thesis, page 39, section "2.4. Store derivations", paragraph 2)

  • Nix [derivation] expressions are first translated to store derivations that live in the Nix store and that each describe a single build action with all variability removed. These store derivations can then be built, which results in derivation outputs that also live in the Nix store.
    (PhD thesis, page 39, section "2.4. Store derivations", paragraph 3)

    Where "derivation outputs" are the built components/packages, I presume.

  • What matters is that each [Nix] derivation [expression] is translated recursively into a store derivation
    (PhD thesis, page 39, section "2.4. Store derivations", paragraph 4)

  • The most important primop, indeed the raison d’être for the Nix expression language, is the primop derivation. It translates a set of attributes describing a build action to a store derivation, which can then be built. The translation process is performed by the function instantiate, given in Section 5.4. What is relevant here is that instantiate(as) takes a set of attributes as, translates them to a store derivation, and returns an identical set of attributes, but with three attributes added: the attribute type with string value "derivation", and the attributes drvPath and outPath containing the store paths of the store derivation and its output, respectively.
    (PhD thesis, page 80, paragraph 2)

  • Store derivations are the result of the evaluation of high-level Nix [derivation] expressions. Nix [derivation] expressions can express variability, store derivations cannot—a store derivation encodes a single, specific, constant
    build action.
    (PhD thesis, page 100, section "5.4. Translating Nix expressions to store derivations", paragraph 1)

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/documenting-what-is-nix/10177/5

@fricklerhandwerk
Copy link
Contributor

@toraritte thank you very much for the clarification and for collecting all the material, this is very valuable.

I think the PhD thesis is fairly underappreciated and more parts should be used from it

Fully agree. I have it handy and try to base the explanation on it as much as possible. It's just that the thesis has a very different structure from what we want to do here. The other thing is that the thesis is not even accessible on the web site any more, so chances are highly reduced that people will even see it.

once a concept/term is introduced, it should be used consistently in the entire document, even if it means increased verbosity.

Absolutely, I will see to it.

@toraritte
Copy link
Contributor

@fricklerhandwerk Thank you!

It's just that the thesis has a very different structure from what we want to do here.

Yes... The explanations are top notch, but unfortunately even definitions/descriptions of the same concepts are scattered all over the place ("derivation" is a case in point). Plus it requires deep understanding in certain topics that makes it hard to consume (at least, for me).

the thesis is not even accessible on the web site any more

:O Why? Thanks for linking that issue. My biggest problem has always been that it is impossible to link to parts of it (which I would have done countless times for questions and answers alike, for example) as it is not available in HTML form.

Another problem with promoting the thesis is that it has been written 16(?) years ago, and because Nix's design has only been documented in issues and pull requests in multiple repos, it takes considerable effort to point out what has changed. (PR #4280 was heartwarming though.) I started annotating the thesis to understand the basics and to point out some of the changes (e.g., organization of Nixpkgs; name -> pname + version; CLI commands; etc.) but again, it's just a huge undertaking.

@Ericson2314
Copy link
Member Author

Yeah a lot of what we are doing is just getting the PhD thesis up to date with today's Nix. There are only a few of us that know what has happened since in broad detail, so it's important get that written down!

@Ericson2314
Copy link
Member Author

PR #4280 was heartwarming though.

To be clear, this is the continuation of that same effort! I just didn't want the work being done in my fork of Nix, which makes it hard for other people to help out. Which I do need!

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Apr 21, 2022

Another ambiguity with wording is about the things Nix actually manages. The thesis calls them components:

Nix is a system for software deployment. The term component will be used to denote the basic units of deployment. These are simply sets of files that implement some arbitrary functionality through an interface. In fact, Nix does not really care what a component actually is. As far as Nix is concerned a component is just a set of files in a file system. That is, we have a very weak notion of component, weaker even than the commonly used definition in [155]. (What we call a component typically corresponds to the ambiguous notion of a package in package management systems. Nix’s notion of components is discussed further in Section 3.1.)
The Purely Functional Software Deployment Model p. 19, §2

[W]hat do we call the smallest meaningful artifacts that are subject to deployment? It is quite customary in some communities to call these packages, but this term has the problem that it implies that the artifact is in packaged form.
The Purely Functional Software Deployment Model p. 49, §3

  • A software component is a software artifact that is subject to automatic composition. It can require, and be required by, other components.
  • A software component is a unit of deployment.

The Purely Functional Software Deployment Model p. 50, §2

The term component appears in the manual with that meaning only here and here, the only exceptions being pre-1.0 release notes.

Most importantly:

It's worth noting that the Nix language is intended as a DSL for package and configuration management, but it has no notions of "packages" or "configurations".
Nix language changes §12 (GitHub Gists do not allow to reference line numbers)

All the material, especially all the internal nixpkgs jargon, seems to have settled on package. It would make sense to me to say that components only become software packages at the point where we give them appropriate semantics. We do that by hooking them into an operating system: fiddle with symlinks to have stuff in the right place and set up PATH. Similar for NixOS and configurations, symlinking files to certain locations and setting environment variables.

In that sense, the package/configuration management aspect of Nix only lives in nix-env and unspecified helper scripts like the installer that sets up the shell to look at special paths we use as entry points.

Does that sound reasonable?

I fully bought into the concept of components from day one, but the term feels inappropriate for everyday use. Also it would require adding a definition to make the term sound meaningful, and that does not seem suitable for a half-pager introduction.

Build Systems à la Carte sec. 3 uses the term value. With @Ericson2314 and @tomberek we figured that the Nix store or the Build Systems Store, just as the terminology in the paper and the conclusion in sec. 8 hint at, is really a trace of a lazily evaluated programming language. Build results are therefore indeed values, build plans/derivations/Tasks are thunks, and the builders are functions.

So while the store API is indeed a language, using values as a term for build results is highly problematic as it would interfere with the configuration language aspect and confuse people even more. I'm inclined to go with data, as that is still fairly vague but goes in the right direction.

Here is a preliminary Rosetta stone for build system terminology, compiled out of desparation.

generic build system Nix Bazel Build Systems à la Carte lazy programming language
data (build input, build result) component file (source, target) value value
build plan derivation rule Task thunk
build instructions builder action function function
build realisation build run evaluation
persistence layer store file system Store evaluation trace, heap

What do you think?

@edolstra
Copy link
Member

The word "component" should be avoided since it is too ambiguous and overloaded.

In Nix, a "build plan" is not a "derivation" but a "derivation graph". Derivations are nodes in that graph. Derivations are a tuple (builder, arguments, environment, ...). So "build instructions" probably corresponds most closely with "derivation". (The "builder" itself can be something like "bash", i.e. does not really provide build instructions on its own.)

The term "realisation" should probably also be avoided since it's overloaded. E.g. we use realisation for building (as in nix-store -r), but also as a mapping between CA derivations and actual outputs.

@toraritte
Copy link
Contributor

toraritte commented Apr 21, 2022

I have been using "build result" for a while now; not flashy at all but, as stated in the thesis, "Nix does not really care what a component actually is. As far as Nix is concerned a component is just a set of files in a file system", and whatever ends up in the Nix store is the output of build actions (whether we are talking about compiling a software, constructing data sets, assembling documents, etc.) (For the sake of bringing examples: https://discourse.nixos.org/t/what-are-interesting-unique-and-or-non-standard-uses-of-nix/12977)

I'm inclined to go with data, as that is still fairly vague but goes in the right direction.

"data" is closer in meaning to what Nix "components" are supposed to represent, but because it is an even more common word, wouldn't its usage be prone to more ambiguity? Some of the examples cited above use the Nix store to house immutable datasets, config files, and so on, so discussions in the context of those projects may become difficult.

Another path (that is fraught with its own perils) may be to come up with a bespoke term specific to Nix (and to similar/related build systems even, such as Guix). The upside is that its usage would be unambiguous but

  1. its meaning will have to be carefully defined so that it won't be perceived as a synonym for "component", "package", etc. (and its official usage (docs, tutorials, etc.) would also have to avoid this mistake)
  2. it would impose yet another cognitive load on users, expecting them to correctly understand it as a unique concept (and hoping to use it accordingly)

Build results are therefore indeed values, build plans/derivations/Tasks are thunks, and the builders are functions.

I love this summary; whatever term will get settled on, I believe including this (somewhere) would be helpful towards understanding. Thank you for compiling the table!

@@ -0,0 +1,37 @@
# Advanced Topic: Related Work
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 this is helpful right now. Let's try to keep new material to a minimum, and collect tangential ideas in private. It's hard to keep track of all that stuff in public, and produces a lot of noise.

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Apr 22, 2022

@edolstra Thank you for the clarification!

@edolstra Derivations are a tuple (builder, arguments, environment, ...). So "build instructions" probably corresponds most closely with "derivation".

While this is true in terms of how Nix is implemented, I disagree conceptually. It is rather arbitrary due to how Unix processes work that there is even a separation between builder, arguments and environment.

What's missing from the tuple is the set of build inputs and the output, right? If we ignore implementation details for a moment, a derivation may as well be (builder, [inputs], output).

@edolstra The "builder" itself can be something like "bash", i.e. does not really provide build instructions on its own.

And that is only because the separation is technically possible and exploited in practice. As far as we are concerned here, it may be an opaque binary that does not take arguments or consider environment variables, reading from a fixed set of file system objects, producing another file system object with a predefined path.

@edolstra In Nix, a "build plan" is not a "derivation" but a "derivation graph". Derivations are nodes in that graph.

Maybe "build plan" is misleading. I picked it up from previous drafts of the overview section. Had read it as a "build not yet made" as opposed to only "instructions", which do not include references to build inputs.

I thought about using "build task" for "derivation", but that does not really sound meaningful, as it does not capture the "build not yet made" idea. What about changing the table in the following way?

generic build system Nix Bazel Build Systems à la Carte lazy programming language
build plan derivation rule Task thunk
build graph derivation graph dependency graph Tasks call graph

@toraritte "data" is closer in meaning to what Nix "components" are supposed to represent, but because it is an even more common word, wouldn't its usage be prone to more ambiguity?

It's just as vague, but has the advantage of not sounding fancy and does not require further definition. I don't see ambiguity as a problem, because the object of interest here is very generic.

@toraritte Some of the examples cited above use the Nix store to house immutable datasets, config files, and so on, so discussions in the context of those projects may become difficult.

All of that is just data.

@toraritte Another path (that is fraught with its own perils) may be to come up with a bespoke term specific to Nix (and to similar/related build systems even, such as Guix). The upside is that its usage would be unambiguous.

What are you referring to here, specifically?

fricklerhandwerk referenced this pull request in nix-community/nix Apr 22, 2022
The idea and most of the execution are @fricklerhandwerk's. I changed a
few things best I could based on @edolstra's corrections, and a Bazel
glossary.

Valentin Gagarin <valentin@fricklerhandwerk.de>
@toraritte
Copy link
Contributor

toraritte commented Apr 22, 2022

@edolstra In Nix, a "build plan" is not a "derivation" but a "derivation graph".

Are the terms below synonyms?

  1. pointer graph ≈ object graph
  2. derivation graph ≈ build graph ≈ dependency graph ≈ references graph

"Figure 3.1.: Deployment / memory management analogies" says that

Programming Language Domain | Deployment Domain Concepts
----------------------------|-------------------------
                           ...
               object graph ⇔ dependency graph

1. pointer graph ≈ object graph

Fairly sure about this one because object graph is only used in figure 3.1 but this quote clears it up:

Other languages address this problem by imposing a pointer discipline: the layouts of memory objects (including the positions of pointers) are known, and programs cannot manipulate pointers arbitrarily. For example, Java does not permit casting between integers and pointers, or direct pointer arithmetic. Along with runtime information of memory layouts, this enables precise determination of the pointer graph.
(PhD thesis, page 56, section "3.4. A pointer discipline", paragraph 3)

2. derivation graph ≈ build graph ≈ dependency graph ≈ references graph

Up until chapter 5, only dependency graph is used but then it states that

The references graph (i.e., the deployment analogue of the pointer graph in programming languages).
(PhD thesis, page 95, section "5.2.3. Path validity and the closure invariant")

so given all the above, pointer graphobject graphdependency graphreferences graph. (Also, the references graph is a product of the references function defined on page 55 that confirms this.)

Derivation graph first shows up on page 108, paragraph 2:

In essence, hashDrv partitions store derivations into equivalence classes, and for hashing purpose it replaces each store path in a derivation graph with its equivalence class. [...couple of lines omitted...] After we have translated a Nix expression to a graph of store derivations, we want to perform the build actions described by them.

It sounds very much like what a dependency graph is, and they also looks a lot alike:

image
image

Build graph's first appearance happens on page 114, paragraph 4 ("determine whether the build graph of a component contains certain “bad” sources") but some lines below is the only part that resembles a definition:

It is worth noting at this point that Nix in no way maintains a link between the build graph (store derivations and sources) in the Nix store on the one hand, and the Nix expressions from which they were instantiated on the other hand.

Many aspects of Nix's operation are still fuzzy to me so I could only guess about this one.


I'm a strong proponent of using terminology consistently in official communications, even if it makes them more verbose and the prose uglier, but if there would be a thesaurus alongside the glossary (or built one into it) that would be just as good.

@toraritte
Copy link
Contributor

toraritte commented Apr 22, 2022

Another path (that is fraught with its own perils) may be to come up with a bespoke term specific to Nix (and to similar/related build systems even, such as Guix). The upside is that its usage would be unambiguous.

@fricklerhandwerk What are you referring to here, specifically?

Basically to create a word for the purpose of replacing "component". This has been a very effective method during the wave of national language reforms throughout history, but not a fan of it in this case, unless the meaning of the new term can be pinned down exactly.

With that said, I like "data" because

  • it is short,
  • it demystifies the contents of the Nix store,
  • and my concerns may just be a form of premature optimization.

I still like "build result" too because

  • it alludes to the process that produces it (i.e., the build instructions in the derivation are realized)
  • and it is widely used both in the thesis, official docs, and posts of users to refer to the end product that ends up in the Nix store.

edit: Totally forgot about atoms so the term "build result" cannot be applied in the general sense...

A basic operation on the Nix store is to add atoms to the store. Atoms are store objects that are not derived, that is, are not built by performing a store derivation. The foremost examples of atoms are sources referenced from derivations in Nix expressions (e.g., builder.sh in Figure 2.6), and store derivations.
(PhD thesis, page 97, section "5.3. Atoms")

@fricklerhandwerk
Copy link
Contributor

@toraritte Thanks for pointing out atoms. I think "source files" as a special case of build inputs is commonplace nowadays.

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Apr 27, 2022

Just read through the excellent Architecture of Gazelle. They are doing everything right: a high-level overview using well-explained or intuitive terminology, linking to details where needed, yet with descriptions concrete enough to make immediate sense in context of this application.

I think we are also moving in the right direction, and maybe should try to observe why the explanation they give is effective to understand the tool.

Gazelle is a tool that generates and updates Bazel build files for Go projects that follow the conventional "go build" project layout. It is intended to simplify the maintenance of Bazel Go projects as much as possible.

X is a tool that does Y to Z. It is intended to W.

This document describes how Gazelle works. It should help users understand why Gazelle behaves as it does, and it should help developers understand how to modify Gazelle and how to write similar tools.

This document describes how X works. It should help users understand why X behaves as it does, and it should help developers understand how to modify X and how to write similar tools.

I simply don't understand why this sort of introduction and overview is not on the front page of every software project and in the first section of every README. I remember that a few years ago someone loudly complained on the internet that the first section of the README should be instructions how to run the shiny new software, because how would I know if is any good if I can't play with it? People seem to have picked it up en masse, and I honestly never got that. How would I know if it is even worth my time to play with it if I don't know what it is supposed to be good for in the first place, and how it tries to achieve that?

@garbas Do I understand correctly that we want to have exactly that as a short-term goal? I really hoped that would be the point of writing the overview.


## Overview

Nix consists of hierarchical [layers](https://en.m.wikipedia.org/wiki/Multitier_architecture#Layers).
Copy link
Member

Choose a reason for hiding this comment

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

Links to mobile version of Wikipedia (here and in the following) probably unintentional?

Copy link
Contributor

Choose a reason for hiding this comment

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

Mobile Wikipedia is intentional, as it is less visual noise and page data.

It is used to compose expressions which ultimately evaluate to self-contained *build plans*, used to derive *build results* from referenced *build inputs*.

::: {.note}
The Nix language itself does not have a notion of *packages* or *configurations*.
Copy link
Member

Choose a reason for hiding this comment

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

I've drafted a definition for package in #6507. It is a bit more minimal and more general than the de facto handling of "packages" by the Nix tools.
Nonetheless, it is not part of the language per se, as it is a convention or interface around expressions.

@fricklerhandwerk
Copy link
Contributor

This is the current state, expressed as a concept map. I consider green items ready to merge, yellow and orange need more work. I would like to un-draft this PR once the colored items are all green. The rest is for a different PR.

flowchart
store --> derivation & building & obj[store object]
derivation & obj --> closure --> gc[garbage collection]
obj --> path & fso[file system object]
building --> scan
derivation --> building --> obj
closure & path[store path] --> scan[reference scanning]

style store fill:green
style obj fill:green
style closure fill:green
style fso fill:yellow
style path fill:orange
Loading

@fricklerhandwerk
Copy link
Contributor

fricklerhandwerk commented Jun 21, 2022

Updated concept map:
(Sorry for confusing arrows, I can't get mermaid to sort them the way I want. The graph is planar.)

flowchart

store --> obj[store object] & closure &  operations
obj --> unix[files and processes] --> fso[file system object] & path
fso --> digest --> ia[input addressing] & ca[content addressing]
digest --> path[store path] --> scan[reference scanning]

operations --> building & gc
closure --> gc[garbage collection] & scan

building --> scan
derivation --> closure & building


style store fill:green
style obj fill:green
style closure fill:green
style fso fill:green
style path fill:green
style unix fill:green
style operations fill:green
style scan fill:yellow
style digest fill:yellow
style ca fill:yellow
style ia fill:yellow
Loading

The still open pull requests against this branch are supposed to nail down the green topics. The yellow topics will have enough content to be workable, but may need to be placed somewhere else and possibly reworded to fit their context.

@fricklerhandwerk
Copy link
Contributor

@edolstra @domenkozar @thufschmitt please take a look. It's a large one, thus there are tons of opportunities for bikeshedding. We did a lot of work on making it clear, concise, and correct.

@Ericson2314 Ericson2314 restored the doc-what-is-nix branch August 4, 2022 22:22
@edolstra
Copy link
Member

edolstra commented Aug 5, 2022

I've hidden the architecture section until I've had a chance to review it (4eb5666). At first glance, a couple of issues:

  • It should probably be a separate book since it serves a different purpose than the (reference) manual.
  • It shouldn't use terms like FSO which aren't used in the actual implementation.
  • Stuff like the build systems a la carte comparison are probably more suitable for a blog post than an architecture reference.

@fricklerhandwerk
Copy link
Contributor

@edolstra in that case, could you please revert the merge commit so we can continue working on the pull request?

@Ericson2314
Copy link
Member Author

It should probably be a separate book since it serves a different purpose than the (reference) manual.

This part confuses me because the intent was to write the reference (bottom right quadrant), with any explanation (bottom left quadrant) a mere bonus.

@Ericson2314 Ericson2314 deleted the doc-what-is-nix branch August 6, 2022 13:43

*(This chapter is unstable and a work in progress. Incoming links may rot.)*

This chapter describes how Nix works.
Copy link
Contributor

Choose a reason for hiding this comment

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

This may sound like splitting hairs, but instead of the word "Nix", the manuals should say explicitly what the term refers to, even if it is to the detriment of brevity.1 Depending on the context, I saw it used to mean:

  • Nix core concepts / paradigm / model
  • Nix CLI tools
  • Nix expression language
  • the implementation of Nix (i.e., the NixOS/nix)
  • the Nix ecosystem as a whole (i.e., NixOS/nix implementation, Nixpkgs, NixOS, even NixOps)
  • Nixpkgs (rarely, but it still)
  • (there is probably more..)

Taking the very next sentence as an example:

It should help users understand why Nix behaves as it does, and it should help developers understand how to modify Nix and how to write similar tools.

  • "NIx behaves": I presume this alludes to the Nix model and/or the implementation
  • "to modify Nix": To modify a Nix expression, the behavior of the Nix CLI tools, the store object in the Nix store - or something else?

I guess the "Architecture" section is about the model itself, and if so, it would be prudent to start with a short explanation what it is about. (It would be nice to have a specification.) Below are two ways I tried to define "Nix model" to myself:

  1. A purely functional deployment model
    ... then explain what purity2, "functional" (this from PR Greatly expand architecture section, including splitting into abstract vs concrete model #6877), and deployment model mean.
    (Took it directly from the thesis; the omission of the word "software" is deliberate.)

  2. A (new) paradigm of building anything that requires assembly3, and managing the build results. The official term for "build result" is store object because they are kept in the Nix store.


[1]: The definition of "Nix" has been a subject of contention on many online forums, but personally, it even made stop trying out Nix in the beginning and to give up on more certain parts of it a couple of times. I found the tutorials, posts, manuals, etc. confusing because sometimes there were sudden context switches, and not knowing what other aspects of NIx there are, I couldn't connect the dots (heh, still can't most of the time).

[2]: Thesis, page 21 (PDF page 29), 2nd paragraph from bottom.

[3]: My first try was "A (new) paradigm of building digital artifacts3 (where the input can be anything that require assembly), and managing the build results., but the term "digital artifact" seems just as overloaded as "component" or "package":

Comment on lines +32 to +34
At the top is the [command line interface](../command-ref/command-ref.md), translating from invocations of Nix executables to interactions with the underlying layers.

Below that is the [Nix expression language](../expressions/expression-language.md), a [purely functional][purely-functional-programming] configuration language.
Copy link
Contributor

Choose a reason for hiding this comment

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

When I started thinking about the term "Nix", this is the hierarchy that helped me put things into perspective:


       ┌────────── Nix MODEL ──────────┐
       │                               │
       │ (This would be a spec, but    │
       │  it is the implementation     │
       │  itself, right?)              │
       │                               │
       └───────────────┬───────────────┘
                       │
                       │
                       │
                       ▼
┌───────────── Nix IMPLEMENTATION ──────────┐
│                 ("the core")              │
│                                           │    e.g., modules/c++ files
│         Implementation of the model       │          implementing flakes
│ (C++ code defining the building blocks of │
│  Nix: Nix lexer & parser, behaviour of    │
│  the Nix store, store objects and actions │
│  etc.)                                    │
│                                           │
└──────────────────────┬────────────────────┘
                       │
                       │
                       │
                       ▼
┌─────────────── Nix FRONTEND ──────────────┐            
│                                           │
│   + CLI tools that use the "core" libs    │    e.g., `nix flakes` commands
│                                           │
│   + Nix lang                              │
│     (Well, it is interpreted by the CLI   │
│      tools, but this is what is used to   │
│      interact with the system. Could be   │
│      wrong.)                              │
│                                           │
└───────────────────────────────────────────┘


## Operations

A Nix store can *add*, *retrieve*, and *delete* store objects.
Copy link
Contributor

Choose a reason for hiding this comment

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

(and line 75 below:)

It can perform builds, that is, create new store objects by transforming build inputs into build outputs, using instructions from the build tasks.

"Nix store" should be the object of the sentence and not the subject. At least, the way I understand it, the Nix store is the input of (or state manipulated by) these operations, and the Nix implementation performs the actions. (That is, the operations are functions defined by NixOS/nix implementation, and called by the CLI tools when invoked.)

Comment on lines +48 to +72

[ data ]
|
V
[ store ] ---> add ----> [ store' ]
|
V
[ reference ]

<!-- -->

[ reference ]
|
V
[ store ] ---> get
|
V
[ store object ]

<!-- -->

[ reference ]
|
V
[ store ] --> delete --> [ store' ]
Copy link
Contributor

Choose a reason for hiding this comment

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

Even with the arrows this representation confused me, until I started thinking about the store as the state of a state machine (this wiki, 1st paragraph & this Erlang doc):

State x Input(s) -> Action(s), State'

So maybe making the figures explicit?

            INPUT               [ data ]
                                    |
                                    V
 STATE TRANSITION   [ store ] ---> add ----> [ store' ]
                                    |
                                    V
           OUTPUT             [ reference ]

            INPUT               [ reference ]
                                    |
                                    V
 STATE TRANSITION   [ store ] ---> get ----> [ store ]
                                    |
                                    V
           OUTPUT             [ store object ]


@toraritte
Copy link
Contributor

@edolstra It should probably be a separate book since it serves a different purpose than the (reference) manual.

@Ericson2314 This part confuses me because the intent was to write the reference (bottom right quadrant), with any explanation (bottom left quadrant) a mere bonus.

Maybe this is what is meant by a "separate book"?

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/summer-of-nix-documentation-stream/20351/4

@fricklerhandwerk
Copy link
Contributor

  • @fricklerhandwerk @infinisil We as the documentation team think the bulk of this material should be in the documentation
    • The reference parts absolutely should
    • The explanation parts help the reference make sense and probably should too
    • There is still plenty of top half (tutorial and how-to guide, per The documentation system) material in the manual we should be able to remove once nix.dev etc. has it instead, so keeping this no material should not "bloat" the manual
  • @Ericson2314 is up to keep on working criticized points
    • But we will need clarification and discussion to figure out what exactly needs to be changed.

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/2022-08-11-documentation-team-meeting-7/20918/1

@blaggacao
Copy link
Contributor

I want to add FYSA a "niche" angle to the discussion, that might be helpful to broaden the perspective: https://divnix.github.io/std/explain/why-nix.html

@fricklerhandwerk
Copy link
Contributor

@blaggacao By virtue of what I do every day for the past three months, I'm very aware of what is going on in the community.

Please add to pull requests only constructive criticism and keep the noise down. Anything else takes a toll on everyone's cognitive resources.

@nixos-discourse
Copy link

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

https://discourse.nixos.org/t/summer-of-nix-documentation-stream/20351/2

fricklerhandwerk added a commit to fricklerhandwerk/nix that referenced this pull request Aug 22, 2022
…nix"

This reverts commit 81e1013, reversing
changes made to 7d1280b.
fricklerhandwerk added a commit that referenced this pull request Sep 9, 2022
Revert #6420 "Document what Nix *is*" so we can start over with smaller change sets
Minion3665 pushed a commit to Minion3665/nix that referenced this pull request Feb 23, 2023
Minion3665 pushed a commit to Minion3665/nix that referenced this pull request Feb 23, 2023
…nix"

This reverts commit 81e1013, reversing
changes made to 7d1280b.
Minion3665 pushed a commit to Minion3665/nix that referenced this pull request Feb 23, 2023
Revert NixOS#6420 "Document what Nix *is*" so we can start over with smaller change sets
@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-05-11-learning-journey-working-group-meeting-notes-8/28120/11

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Archived in project
Development

Successfully merging this pull request may close these issues.

10 participants