Функция nix для рекурсивного объединения атрибутов / записей и объединения массивов - PullRequest
0 голосов
/ 03 февраля 2019

Кто-нибудь знает такую ​​функцию, которая объединяет список записей

  • , если все значения для слияния являются записями - слить их рекурсивно
  • , если все значения для слияния являются массивами - объединять массивы
  • Если значения не могут быть объединены - последнее значение предпочтительнее

Пример 1:

recursiveMergeAttrs [
  { a = "x"; c = "m"; list = [1]; }
  { a = "y"; b = "z"; list = [2]; }
]

returns

{ a = "y"; b = "z"; c="m"; list = [1 2] }

Пример 2

recursiveMergeAttrs [
  {
    boot.loader.grub.enable = true;
    boot.loader.grub.device = "/dev/hda";
  }
  {
    boot.loader.grub.device = "";
  }
]

returns

{
  boot.loader.grub.enable = true;
  boot.loader.grub.device = "";
}

PS

recursiveUpdate не работает

recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets

recursiveMergeAttrs [ { a = "x"; c = "m"; list = [1]; } { a = "y"; b = "z"; list = [2]; } ]

returns 

{ a = "y"; b = "z"; c = "m"; list = [ 2 ]; }

1 Ответ

0 голосов
/ 03 февраля 2019

Сделал это

{ lib, ... }:

with lib;

/*
  Merges list of records, concatenates arrays, if two values can't be merged - the latter is preferred

  Example 1:
    recursiveMerge [
      { a = "x"; c = "m"; list = [1]; }
      { a = "y"; b = "z"; list = [2]; }
    ]

    returns

    { a = "y"; b = "z"; c="m"; list = [1 2] }

  Example 2:
    recursiveMerge [
      {
        a.a = [1];
        a.b = 1;
        a.c = [1 1];
        boot.loader.grub.enable = true;
        boot.loader.grub.device = "/dev/hda";
      }
      {
        a.a = [2];
        a.b = 2;
        a.c = [1 2];
        boot.loader.grub.device = "";
      }
    ]

    returns

    { a = { a = [ 1 2 ]; b = 2; c = [ 1 2 ]; }; boot = { loader = { grub = { device = ""; enable = true; }; }; }; }

*/

let

recursiveMerge = attrList:
  let f = attrPath:
    zipAttrsWith (n: values:
      if tail values == []
      then head values
      else
        if all isList values
        then unique (concatLists values)
        else
          if all isAttrs values
          then f (attrPath ++ [n]) values
          else last values
    );
  in f [] attrList;

in

recursiveMerge
...