nixnixos

Deeply merge sets in Nix


in Nix, you can use // to merge two sets and replace the lefts attributes with the right ones if they're double, however. In this example:

let 
  
  set_one = {
    nested_set = {
        some_value_that_will_be_lost = "some forgotten value";
        some_attribute = "some value";
    };
  };

  set_two = {
    nested_set = {
        some_attribute = "some other value";
    };
  };

in ( set_one // set_two )

will result in:

{
    nested_set = {
        some_attribute = "some other value";
    };
}

while I am expecting:

{
    nested_set = {
        some_value_that_will_be_lost = "some forgotten value";
        some_attribute = "some other value";
    };
}

I tried to see if lib had any useful functions, and I found lib.modules.mergeModules, and tried:

let 

  lib = (import <nixpkgs> { }).pkgs.lib;

  set_one = {
    nested_set = {
        some_value_that_will_be_lost = "some forgotten value";
        some_attribute = "some value";
    };
  };

  set_two = {
    nested_set = {
        some_attribute = "some other value";
    };
  };

in ( lib.modules.mergeModules set_one set_two )

But that module was depricated, and only resulted in errors.

The problem is that I want the implementation to work regardless of what the set is. Is there a way to do this that you know of to deeply/recursively merge two sets without knowing it's contents?


Solution

  • See lib.attrsets.recursiveUpdate

    let
      pkgs = import <nixpkgs> {};
      lib = pkgs.lib;
      set_one = {
        nested_set = {
          some_value_that_will_be_lost = "some forgotten value";
          some_attribute = "some value";
        };
      };
      set_two = {
        nested_set = {
          some_attribute = "some other value";
        };
      };
    in
    lib.recursiveUpdate set_one set_two
    

    evaluates to

    { nested_set = { some_attribute = "some other value"; some_value_that_will_be_lost = "some forgotten value"; }; }