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`.
71 : 1\. Function argument
81 ## `lib.fixedPoints.fix` usage example
84 fix (self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; })
85 => { bar = "bar"; foo = "foo"; foobar = "foobar"; }
87 fix (self: [ 1 2 (elemAt self 0 + elemAt self 1) ])
93 fix = f: let x = f x; in x;
96 A variant of `fix` that records the original recursive attribute set in the
97 result, in an attribute named `__unfix__`.
99 This is useful in combination with the `extends` function to
100 implement deep overriding.
107 : 1\. Function argument
109 fix' = f: let x = f x // { __unfix__ = f; }; in x;
112 Return the fixpoint that `f` converges to when called iteratively, starting
116 nix-repl> converge (x: x / 2) 16
125 : 1\. Function argument
129 : 2\. Function argument
146 Extend a function using an overlay.
148 Overlays allow modifying and extending fixed-point functions, specifically ones returning attribute sets.
149 A fixed-point function is a function which is intended to be evaluated by passing the result of itself as the argument.
150 This is possible due to Nix's lazy evaluation.
153 A fixed-point function returning an attribute set has the form
156 final: { # attributes }
159 where `final` refers to the lazily evaluated attribute set returned by the fixed-point function.
161 An overlay to such a fixed-point function has the form
164 final: prev: { # attributes }
167 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.
169 Applying an overlay is done with `extends`:
173 f = final: { # attributes };
174 overlay = final: prev: { # attributes };
175 in extends overlay f;
178 To get the value of `final`, use `lib.fix`:
182 f = final: { # attributes };
183 overlay = final: prev: { # attributes };
184 g = extends overlay f;
189 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.
191 The given fixed-point function is called with a separate argument than if it was evaluated with `lib.fix`.
196 # Extend a fixed-point function with an overlay
198 Define a fixed-point function `f` that expects its own output as the argument `final`:
205 # b depends on the final value of a, available as final.a
210 Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) to get the final result:
217 An overlay represents a modification or extension of such a fixed-point function.
218 Here's an example of an overlay:
221 overlay = final: prev: {
222 # Modify the previous value of a, available as prev.a
225 # Extend the attribute set with c, letting it depend on the final values of a and b
226 c = final.a + final.b;
230 Use `extends overlay f` to apply the overlay to the fixed-point function `f`.
231 This produces a new fixed-point function `g` with the combined behavior of `f` and `overlay`:
234 g = extends overlay f
237 The result is a function, so we can't print it directly, but it's the same as:
241 # The constant from f, but changed with the overlay
247 # Extended in the overlay
248 c = final.a + final.b;
252 Evaluate this using [`lib.fix`](#function-library-lib.fixedPoints.fix) again to get the final result:
256 => { a = 11; b = 13; c = 24; }
265 : The overlay to apply to the fixed-point function
269 : The fixed-point function
274 extends :: (Attrs -> Attrs -> Attrs) # The overlay to apply to the fixed-point function
275 -> (Attrs -> Attrs) # A fixed-point function
276 -> (Attrs -> Attrs) # The resulting fixed-point function
281 ## `lib.fixedPoints.extends` usage example
284 f = final: { a = 1; b = final.a + 2; }
289 fix (extends (final: prev: { a = prev.a + 10; }) f)
290 => { a = 11; b = 13; }
292 fix (extends (final: prev: { b = final.a + 5; }) f)
295 fix (extends (final: prev: { c = final.a + final.b; }) f)
296 => { a = 1; b = 3; c = 4; }
304 # The result should be thought of as a function, the argument of that function is not an argument to `extends` itself
310 prev // overlay final prev
314 Compose two extending functions of the type expected by 'extends'
315 into one where changes made in the first are available in the
316 'super' of the second
323 : 1\. Function argument
327 : 2\. Function argument
331 : 3\. Function argument
335 : 4\. Function argument
339 let fApplied = f final prev;
340 prev' = prev // fApplied;
341 in fApplied // g final prev';
344 Compose several extending functions of the type expected by 'extends' into
345 one where changes made in preceding functions are made available to
349 composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
350 ^final ^prev ^overrides ^final ^prev ^overrides
353 composeManyExtensions =
354 lib.foldr (x: y: composeExtensions x y) (final: prev: {});
357 Create an overridable, recursive attribute set. For example:
360 nix-repl> obj = makeExtensible (self: { })
363 { __unfix__ = «lambda»; extend = «lambda»; }
365 nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
368 { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
370 nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
373 { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
376 makeExtensible = makeExtensibleWithCustomName "extend";
379 Same as `makeExtensible` but the name of the extending attribute is
387 : 1\. Function argument
391 : 2\. Function argument
393 makeExtensibleWithCustomName = extenderName: rattrs:
394 fix' (self: (rattrs self) // {
395 ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);