Growing

It's important to take a small detour at this point and explore the std.grow/std.growOn functions in detail. In particular, it helps to inspect the output of our flake to better understand what it is that these grow functions are generating.

If we refer back to our flake, we will recall that we used the growOn function for generating the flake output. Let's assume for a second that we instead chose to use the std.grow function. If we were to inspect our flake output at this point, we would see something similar to this:

$ nix flake show
git+file:///Users/josh/code/std-book-example
├───__std: unknown
├───aarch64-darwin: unknown
├───aarch64-linux: unknown
├───x86_64-darwin: unknown
└───x86_64-linux: unknown

This looks strange at first; what is under __std? This attribute is generated by the grow functions and is referred to as the registry. It houses a plethora of information about our standardized environment, and you can inspect what's under here by running:

nix eval --json .#__std | jq

The output is large, so it will be omitted here, but essentially it describes our entire environment, including what cells we have, the blocks (and their types) of those cells, what actions we can run on the blocks, etc. The benefit here is that it provides a layer by which external tools can utilize the information gathered about our environment.

What about all the unknowns? There is data here, but it's important to understand that it doesn't conform to the expected flake output schema, so nix flake show just marks it as "unknown." Again, we can see the structure by going into the Nix REPL environment:

$ nix repl
Welcome to Nix 2.10.3. Type :? for help.

nix-repl> :lf .
Added 18 variables.

nix-repl> :p aarch64-darwin
{ std-example = { apps = { default = «derivation /nix/store/rb7jvsds8wxcrxzfz8cc7jpgqsxch8w1-std-example-0.1.0.drv»; }; }; }

In other words, we could run our binary using:

$ nix run .#aarch64-darwin.std-example.apps.default world
Hello, world!

However, this isn't very intuitive, and this is why the growOn function becomes helpful. It allows us to add a compatibility layer by transforming the above structure into something that the Nix CLI can more easily understand. In our case, if we run the same nix flake show command with the growOn function, we see:

$ nix flake show
git+file:///Users/josh/code/std-book-example
├───__functor: unknown
├───__std: unknown
├───aarch64-darwin: unknown
├───aarch64-linux: unknown
├───packages
│   ├───aarch64-darwin
│   │   └───default: package 'example-0.1.0'
│   ├───aarch64-linux
│   │   └───default: package 'example-0.1.0'
│   ├───x86_64-darwin
│   │   └───default: package 'example-0.1.0'
│   └───x86_64-linux
│       └───default: package 'example-0.1.0'
├───x86_64-darwin: unknown
└───x86_64-linux: unknown

This now allows us to run our binary using:

$ nix run .#default world
Hello, world!