OFFSET偏移
← All articlesOFFSET / FIELD NOTESNO. 023

Nix attribute sets: recursion and merging

Distinguish shallow merging in the language from the merging rules for NixOS module options.

English translation · Code and commands follow the Chinese original.

IN THESE READING PATHSThe Nix language and build model ↗
About 2 min readStart reading

"The heart of Nix configuration: finding the right merge point in a complex hierarchy."


Recursive Attribute Sets: rec { ... }#

An ordinary attribute set does not add its own attributes to the lexical scope. To reference attributes by name from within the set, use rec or define shared bindings in a let expression first. If an outer variable has the same name, an ordinary attribute set references that outer variable.

Incorrect:

{
  a = 1;
  b = a + 1; # 报错:变量 a 找不到
}

Correct:

rec {
  a = 1;
  b = a + 1; # 结果为 b = 2
}

How Attribute Merging Really Works#

1. Using // (Merge)

This is merging at the Nix language level.

let
  defaults = { user = "guest"; shell = "/bin/sh"; };
  overrides = { shell = "/bin/bash"; };
in defaults // overrides
# 结果:{ user = "guest"; shell = "/bin/bash"; }
  • Note: // performs a shallow merge. If both sets contain nested sets with the same name, the latter replaces the former outright.

2. Using lib.mkMerge (NixOS Modules Only)

In NixOS configuration files, we rarely use // directly. The NixOS module system merges configuration for us:

{
  environment.systemPackages = [ pkgs.git ];
}
# 另一个模块中:
{
  environment.systemPackages = [ pkgs.vim ];
}
# 结果:[ pkgs.git pkgs.vim ] (列表选项默认按模块规则合并;顺序可用 mkBefore/mkAfter 调整)

Dotted Paths#

Use dotted paths to define deeply nested attributes directly and reduce nesting.

Long form:

{
  services = {
    openssh = {
      enable = true;
    };
  };
}

Concise form:

{
  services.openssh.enable = true;
}

Practical Example: Dynamic Attribute Names#

Use ${...} to generate attribute names dynamically.

let
  username = "alice";
in {
  users.users."${username}" = {
    isNormalUser = true;
  };
}

References & further reading

  1. NixOS Manual ↗
  2. Nix Language Manual ↗

Adapted from technical notes. Examples use generic names.

Continue along a reading path

The Nix language and build model

  1. 01Nix and NixOS: storage, rollback, and declarative thinking
  2. 02Nix syntax: attribute sets, lists, and built-in functions
  3. 03Nix functions and scope
  4. 04Nix attribute sets: recursion and merging
  5. 05Derivations: from expressions to build outputs
CONTINUE READING / NEXT ARTICLEDerivations: from expressions to build outputs

Trace the relationship between evaluation, building or downloading substitutes, and store outputs.