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 Modify the contents of an explicitly recursive attribute set in a way that
107 honors `self`-references. This is accomplished with a function
110 g = self: super: { foo = super.foo + " + "; }
113 that has access to the unmodified input (`super`) as well as the final
114 non-recursive representation of the attribute set (`self`). `extends`
115 differs from the native `//` operator insofar as that it's applied *before*
116 references to `self` are resolved:
119 nix-repl> fix (extends g f)
120 { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; }
123 The name of the function is inspired by object-oriented inheritance, i.e.
124 think of it as an infix operator `g extends f` that mimics the syntax from
125 Java. It may seem counter-intuitive to have the "base class" as the second
126 argument, but it's nice this way if several uses of `extends` are cascaded.
128 To get a better understanding how `extends` turns a function with a fix
129 point (the package set we start with) into a new function with a different fix
130 point (the desired packages set) lets just see, how `extends g f`
131 unfolds with `g` and `f` defined above:
134 extends g f = self: let super = f self; in super // g self super;
135 = self: let super = { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }; in super // g self super
136 = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // g self { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
137 = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // { foo = "foo" + " + "; }
138 = self: { foo = "foo + "; bar = "bar"; foobar = self.foo + self.bar; }
141 extends = f: rattrs: self: let super = rattrs self; in super // f self super;
144 Compose two extending functions of the type expected by 'extends'
145 into one where changes made in the first are available in the
146 'super' of the second
150 let fApplied = f final prev;
151 prev' = prev // fApplied;
152 in fApplied // g final prev';
155 Compose several extending functions of the type expected by 'extends' into
156 one where changes made in preceding functions are made available to
160 composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
161 ^final ^prev ^overrides ^final ^prev ^overrides
164 composeManyExtensions =
165 lib.foldr (x: y: composeExtensions x y) (final: prev: {});
168 Create an overridable, recursive attribute set. For example:
171 nix-repl> obj = makeExtensible (self: { })
174 { __unfix__ = «lambda»; extend = «lambda»; }
176 nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
179 { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
181 nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
184 { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
187 makeExtensible = makeExtensibleWithCustomName "extend";
190 Same as `makeExtensible` but the name of the extending attribute is
193 makeExtensibleWithCustomName = extenderName: rattrs:
194 fix' (self: (rattrs self) // {
195 ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);