= Attribute set operations

== Selection

The `.` operator selects an attribute from a set.

[source]
.Example
....
nix-repl> animal = { name = { first = "Professor"; last = "Paws"; }; age = 10; species = "cat"; }

nix-repl> animal . age
10

nix-repl> animal . name . first
"Professor"
....

== Query

We can use the `?` operator to find out if a set has a particular attribute.

[source]
.Example
....
nix-repl> animal ? species
true

nix-repl> animal ? bicycle
false
....

== Union

We can use the `//` operator to combine two attribute sets.
Attributes in the right-hand set take preference.

[source]
.Example
....
nix-repl> a = { x = 7; y = "hello"; }

nix-repl> b = { y = "wombat"; z = 3; }

nix-repl> a // b
{
  x = 7;
  y = "wombat";
  z = 3;
}
....

This is often used to "modify" one or more values in the set.
Recall that Nix values are immutable, so the result is a new value (the original is not actually modified).

[source]
.Example
....
nix-repl> animal // { species = "tiger"; }
{ age = 10; name = { ... }; species = "tiger"; }
....

[#rec-attrset]
== Recursive attribute sets

An ordinary attribute set cannot refer to its own elements.
To do this, you need a _recursive_ attribute set.

[source]
.Example
....
nix-repl> { x = 3; y = 4*x; }
error: undefined variable 'x'

       at «string»:1:16:

            1| { x = 3; y = 4*x; }
             |                ^

nix-repl> rec { x = 3; y = 4*x; }
{ x = 3; y = 12; }
....

== Useful built-in functions for attribute sets

Nix provides some built-in functions for working with attribute sets;
a few examples are shown below.
For more information on these and other built-in functions, see the Nix Manual
(https://nixos.org/manual/nix/stable/language/builtins).

Get an alphabetical list of the keys.

[source]
.Example
....
nix-repl> builtins.attrNames animal
[ "age" "name" "species" ]
....

Get the values associated with each key, in alphabetical order by the key names.

[source]
.Example
....
nix-repl> builtins.attrValues animal
[ 10 "Professor Paws" "cat" ]
....

What value is associated with a key?

[source]
.Example
....
nix-repl> builtins.getAttr "age" animal
10
....

Does the set have a value for a key?

[source]
.Example
....
nix-repl> builtins.hasAttr "name" animal
true

nix-repl> builtins.hasAttr "car" animal
false
....

Remove one or more keys and associated values from a set.

[source]
.Example
....
nix-repl> builtins.removeAttrs animal [ "age" "species" ]
{ name = "Professor Paws"; }
....

Display an attribute set, including nested sets.

[source]
.Example
....
nix-repl> builtins.toJSON animal
"{\"age\":10,\"name\":{\"first\":\"Professor\",\"last\":\"Paws\"},\"species\":\"cat\"}"
....

