query
On this page

recursiveUpdateUntil

lib.recursiveUpdateUntil

Docs pulled from | This Revision | 35 minutes ago


Update lhs so that rhs wins for any given attribute path that occurs in both.

Unlike the // (update) operator, which operates on a single attribute set, This function views its operands lhs and rhs as a mapping from attribute paths to values.

The caller-provided function pred decides whether any given path is one of the following:

  • true: a value in the mapping
  • false: an attribute set whose purpose is to create the nesting structure.

Inputs

pred

Predicate function (of type List String -> Any -> Any -> Bool)

Inputs:

  • path : List String: the path to the current attribute as a list of strings for attribute names
  • lhsAtPath : Any: the value at that path in lhs; same as getAttrFromPath path lhs
  • rhsAtPath : Any: the value at that path in rhs; same as getAttrFromPath path rhs

Output:

  • true: path points to a value in the mapping, and rhsAtPath will appear in the return value of recursiveUpdateUntil
  • false: path is part of the nesting structure and will be an attrset in the return value of recursiveUpdateUntil

pred is only called for paths that extend prefixes for which pred returned false.

lhs

Left attribute set of the update.

rhs

Right attribute set of the update.

Type

recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet

Examples

lib.attrsets.recursiveUpdateUntil usage example

recursiveUpdateUntil (path: lhs: rhs: path == ["foo"]) {
  # left attribute set
  foo.bar = 1;
  foo.baz = 2;
  bar = 3;
} {
  # right attribute set
  foo.bar = 1;
  foo.quz = 2;
  baz = 4;
}

=> {
  foo.bar = 1; # 'foo.*' from the 'right' set
  foo.quz = 2; #
  bar = 3;     # 'bar' from the 'left' set
  baz = 4;     # 'baz' from the 'right' set
}
(lib.attrsets.recursiveUpdateUntil)

Noogle detected

Aliases

Implementation

The following is the current implementation of this function.

recursiveUpdateUntil =
    pred: lhs: rhs:
    let
      f =
        attrPath:
        zipAttrsWith (
          name: values:
          let
            here = attrPath ++ [ name ];
          in
          if length values == 1 || pred here (elemAt values 1) (head values) then
            head values
          else
            f here values
        );
    in
    f [ ] [ rhs lhs ];