query
On this page

extends

lib.extends

Docs pulled from | This Revision | 31 minutes ago


Extend a function using an overlay.

Overlays allow modifying and extending fixed-point functions, specifically ones returning attribute sets. A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument. This is possible due to Nix's lazy evaluation.

A fixed-point function returning an attribute set has the form

final: { # attributes }

where final refers to the lazily evaluated attribute set returned by the fixed-point function.

An overlay to such a fixed-point function has the form

final: prev: { # attributes }

where prev refers to the result of the original function to final, and final is the result of the composition of the overlay and the original function.

Applying an overlay is done with extends:

let
  f = final: { # attributes };
  overlay = final: prev: { # attributes };
in extends overlay f;

To get the value of final, use lib.fix:

let
  f = final: { # attributes };
  overlay = final: prev: { # attributes };
  g = extends overlay f;
in fix g

The argument to the given fixed-point function after applying an overlay will not refer to its own return value, but rather to the value after evaluating the overlay function.

The given fixed-point function is called with a separate argument than if it was evaluated with lib.fix.

Extend a fixed-point function with an overlay

Define a fixed-point function f that expects its own output as the argument final:

f = final: {
  # Constant value a
  a = 1;

  # b depends on the final value of a, available as final.a
  b = final.a + 2;
}

Evaluate this using lib.fix to get the final result:

fix f
=> { a = 1; b = 3; }

An overlay represents a modification or extension of such a fixed-point function. Here's an example of an overlay:

overlay = final: prev: {
  # Modify the previous value of a, available as prev.a
  a = prev.a + 10;

  # Extend the attribute set with c, letting it depend on the final values of a and b
  c = final.a + final.b;
}

Use extends overlay f to apply the overlay to the fixed-point function f. This produces a new fixed-point function g with the combined behavior of f and overlay:

g = extends overlay f

The result is a function, so we can't print it directly, but it's the same as:

g' = final: {
  # The constant from f, but changed with the overlay
  a = 1 + 10;

  # Unchanged from f
  b = final.a + 2;

  # Extended in the overlay
  c = final.a + final.b;
}

Evaluate this using lib.fix again to get the final result:

fix g
=> { a = 11; b = 13; c = 24; }

Inputs

overlay

The overlay to apply to the fixed-point function

f

The fixed-point function

Type

extends :: (Attrs -> Attrs -> Attrs) # The overlay to apply to the fixed-point function
        -> (Attrs -> Attrs) # A fixed-point function
        -> (Attrs -> Attrs) # The resulting fixed-point function

Examples

extends usage example

f = final: { a = 1; b = final.a + 2; }

fix f
=> { a = 1; b = 3; }

fix (extends (final: prev: { a = prev.a + 10; }) f)
=> { a = 11; b = 13; }

fix (extends (final: prev: { b = final.a + 5; }) f)
=> { a = 1; b = 6; }

fix (extends (final: prev: { c = final.a + final.b; }) f)
=> { a = 1; b = 3; c = 4; }
(lib.fixedPoints.extends)

Noogle also knows

Aliases