4 `fix f` computes the fixed point of the given function `f`. In other words, the return value is `x` in `x = f x`.
6 `f` must be a lazy function.
7 This means that `x` must be a value that can be partially evaluated,
8 such as an attribute set, a list, or a function.
9 This way, `f` can use one part of `x` to compute another part.
11 **Relation to syntactic recursion**
13 This section explains `fix` by refactoring from syntactic recursion to a call of `fix` instead.
15 For context, Nix lets you define attributes in terms of other attributes syntactically using the [`rec { }` syntax](https://nixos.org/manual/nix/stable/language/constructs.html#recursive-sets).
23 { bar = "bar"; foo = "foo"; foobar = "foobar"; }
26 This is convenient when constructing a value to pass to a function for example,
27 but an equivalent effect can be achieved with the `let` binding syntax:
30 nix-repl> let self = {
33 foobar = self.foo + self.bar;
35 { bar = "bar"; foo = "foo"; foobar = "foobar"; }
38 But in general you can get more reuse out of `let` bindings by refactoring them to a function.
44 foobar = self.foo + self.bar;
48 This is where `fix` comes in, it contains the syntactic recursion that's not in `f` anymore.
52 let self = f self; in self;
55 By applying `fix` we get the final result.
59 { bar = "bar"; foo = "foo"; foobar = "foobar"; }
62 Such a refactored `f` using `fix` is not useful by itself.
63 See [`extends`](#function-library-lib.fixedPoints.extends) for an example use case.
64 There `self` is also often called `final`.
66 Type: fix :: (a -> a) -> a
69 fix (self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; })
70 => { bar = "bar"; foo = "foo"; foobar = "foobar"; }
72 fix (self: [ 1 2 (elemAt self 0 + elemAt self 1) ])
75 fix = f: let x = f x; in x;
78 A variant of `fix` that records the original recursive attribute set in the
79 result, in an attribute named `__unfix__`.
81 This is useful in combination with the `extends` function to
82 implement deep overriding.
84 fix' = f: let x = f x // { __unfix__ = f; }; in x;
87 Return the fixpoint that `f` converges to when called iteratively, starting
91 nix-repl> converge (x: x / 2) 16
95 Type: (a -> a) -> a -> a
106 Extend a function using an overlay.
108 Overlays allow modifying and extending fixed-point functions, specifically ones returning attribute sets.
109 A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument.
110 This is possible due to Nix's lazy evaluation.
113 A fixed-point function returning an attribute set has the form
116 final: { # attributes }
119 where `final` refers to the lazily evaluated attribute set returned by the fixed-point function.
121 An overlay to such a fixed-point function has the form
124 final: prev: { # attributes }
127 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.
129 Applying an overlay is done with `extends`:
133 f = final: { # attributes };
134 overlay = final: prev: { # attributes };
135 in extends overlay f;
138 To get the value of `final`, use `lib.fix`:
142 f = final: { # attributes };
143 overlay = final: prev: { # attributes };
144 g = extends overlay f;
149 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.
151 The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
156 # Extend a fixed-point function with an overlay
158 Define a fixed-point function `f` that expects its own output as the argument `final`:
165 # b depends on the final value of a, available as final.a
170 Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) to get the final result:
177 An overlay represents a modification or extension of such a fixed-point function.
178 Here's an example of an overlay:
181 overlay = final: prev: {
182 # Modify the previous value of a, available as prev.a
185 # Extend the attribute set with c, letting it depend on the final values of a and b
186 c = final.a + final.b;
190 Use `extends overlay f` to apply the overlay to the fixed-point function `f`.
191 This produces a new fixed-point function `g` with the combined behavior of `f` and `overlay`:
194 g = extends overlay f
197 The result is a function, so we can't print it directly, but it's the same as:
201 # The constant from f, but changed with the overlay
207 # Extended in the overlay
208 c = final.a + final.b;
212 Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) again to get the final result:
216 => { a = 11; b = 13; c = 24; }
221 extends :: (Attrs -> Attrs -> Attrs) # The overlay to apply to the fixed-point function
222 -> (Attrs -> Attrs) # A fixed-point function
223 -> (Attrs -> Attrs) # The resulting fixed-point function
226 f = final: { a = 1; b = final.a + 2; }
231 fix (extends (final: prev: { a = prev.a + 10; }) f)
232 => { a = 11; b = 13; }
234 fix (extends (final: prev: { b = final.a + 5; }) f)
237 fix (extends (final: prev: { c = final.a + final.b; }) f)
238 => { a = 1; b = 3; c = 4; }
241 # The overlay to apply to the fixed-point function
243 # The fixed-point function
245 # Wrap with parenthesis to prevent nixdoc from rendering the `final` argument in the documentation
246 # The result should be thought of as a function, the argument of that function is not an argument to `extends` itself
252 prev // overlay final prev
256 Compose two extending functions of the type expected by 'extends'
257 into one where changes made in the first are available in the
258 'super' of the second
262 let fApplied = f final prev;
263 prev' = prev // fApplied;
264 in fApplied // g final prev';
267 Compose several extending functions of the type expected by 'extends' into
268 one where changes made in preceding functions are made available to
272 composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
273 ^final ^prev ^overrides ^final ^prev ^overrides
276 composeManyExtensions =
277 lib.foldr (x: y: composeExtensions x y) (final: prev: {});
280 Create an overridable, recursive attribute set. For example:
283 nix-repl> obj = makeExtensible (self: { })
286 { __unfix__ = «lambda»; extend = «lambda»; }
288 nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
291 { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
293 nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
296 { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
299 makeExtensible = makeExtensibleWithCustomName "extend";
302 Same as `makeExtensible` but the name of the extending attribute is
305 makeExtensibleWithCustomName = extenderName: rattrs:
306 fix' (self: (rattrs self) // {
307 ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);