summary refs log tree commit diff
diff options
context:
space:
mode:
authorRobert Hensing <robert@roberthensing.nl>2023-07-08 18:43:36 +0200
committerRobert Hensing <robert@roberthensing.nl>2023-07-08 18:46:08 +0200
commitaa1beb0ab589b017a80927282d3ab60553071f71 (patch)
tree6e13b0aa60eac6bf99ca7c4991f137ffc10130e4
parente08fab0406465bc1ba9f4d2895159c89e952ad71 (diff)
downloadnixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.tar
nixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.tar.gz
nixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.tar.bz2
nixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.tar.lz
nixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.tar.xz
nixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.tar.zst
nixpkgs-aa1beb0ab589b017a80927282d3ab60553071f71.zip
doc: Render lib.fixedPoints
-rw-r--r--doc/default.nix1
-rw-r--r--doc/doc-support/lib-function-docs.nix17
-rw-r--r--lib/fixed-points.nix196
3 files changed, 126 insertions, 88 deletions
diff --git a/doc/default.nix b/doc/default.nix
index 5954e4495ad..8efa406ec1e 100644
--- a/doc/default.nix
+++ b/doc/default.nix
@@ -11,6 +11,7 @@ let
       { name = "strings"; description = "string manipulation functions"; }
       { name = "versions"; description = "version string functions"; }
       { name = "trivial"; description = "miscellaneous functions"; }
+      { name = "fixedPoints"; baseName = "fixed-points"; description = "explicit recursion functions"; }
       { name = "lists"; description = "list manipulation functions"; }
       { name = "debug"; description = "debugging functions"; }
       { name = "options"; description = "NixOS / nixpkgs option handling"; }
diff --git a/doc/doc-support/lib-function-docs.nix b/doc/doc-support/lib-function-docs.nix
index 018b0bd5e94..8592fafbbd1 100644
--- a/doc/doc-support/lib-function-docs.nix
+++ b/doc/doc-support/lib-function-docs.nix
@@ -14,13 +14,16 @@ stdenv.mkDerivation {
   buildInputs = [ nixdoc ];
   installPhase = ''
     function docgen {
-      # TODO: wrap lib.$1 in <literal>, make nixdoc not escape it
-      if [[ -e "../lib/$1.nix" ]]; then
-        nixdoc -c "$1" -d "lib.$1: $2" -l ${locationsJSON} -f "$1.nix" > "$out/$1.md"
+      name=$1
+      baseName=$2
+      description=$3
+      # TODO: wrap lib.$name in <literal>, make nixdoc not escape it
+      if [[ -e "../lib/$baseName.nix" ]]; then
+        nixdoc -c "$name" -d "lib.$name: $description" -l ${locationsJSON} -f "$baseName.nix" > "$out/$name.md"
       else
-        nixdoc -c "$1" -d "lib.$1: $2" -l ${locationsJSON} -f "$1/default.nix" > "$out/$1.md"
+        nixdoc -c "$name" -d "lib.$name: $description" -l ${locationsJSON} -f "$baseName/default.nix" > "$out/$name.md"
       fi
-      echo "$out/$1.md" >> "$out/index.md"
+      echo "$out/$name.md" >> "$out/index.md"
     }
 
     mkdir -p "$out"
@@ -29,8 +32,8 @@ stdenv.mkDerivation {
     ```{=include=} sections
     EOF
 
-    ${lib.concatMapStrings ({ name, description }: ''
-      docgen ${name} ${lib.escapeShellArg description}
+    ${lib.concatMapStrings ({ name, baseName ? name, description }: ''
+      docgen ${name} ${baseName} ${lib.escapeShellArg description}
     '') libsets}
 
     echo '```' >> "$out/index.md"
diff --git a/lib/fixed-points.nix b/lib/fixed-points.nix
index 926428293c1..a63f349b713 100644
--- a/lib/fixed-points.nix
+++ b/lib/fixed-points.nix
@@ -1,34 +1,49 @@
 { lib, ... }:
 rec {
-  # Compute the fixed point of the given function `f`, which is usually an
-  # attribute set that expects its final, non-recursive representation as an
-  # argument:
-  #
-  #     f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
-  #
-  # Nix evaluates this recursion until all references to `self` have been
-  # resolved. At that point, the final result is returned and `f x = x` holds:
-  #
-  #     nix-repl> fix f
-  #     { bar = "bar"; foo = "foo"; foobar = "foobar"; }
-  #
-  #  Type: fix :: (a -> a) -> a
-  #
-  # See https://en.wikipedia.org/wiki/Fixed-point_combinator for further
-  # details.
+  /*
+    Compute the fixed point of the given function `f`, which is usually an
+    attribute set that expects its final, non-recursive representation as an
+    argument:
+
+    ```
+    f = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
+    ```
+
+    Nix evaluates this recursion until all references to `self` have been
+    resolved. At that point, the final result is returned and `f x = x` holds:
+
+    ```
+    nix-repl> fix f
+    { bar = "bar"; foo = "foo"; foobar = "foobar"; }
+    ```
+
+    Type: fix :: (a -> a) -> a
+
+    See https://en.wikipedia.org/wiki/Fixed-point_combinator for further
+    details.
+  */
   fix = f: let x = f x; in x;
 
-  # A variant of `fix` that records the original recursive attribute set in the
-  # result. This is useful in combination with the `extends` function to
-  # implement deep overriding. See pkgs/development/haskell-modules/default.nix
-  # for a concrete example.
+  /*
+    A variant of `fix` that records the original recursive attribute set in the
+    result, in an attribute named `__unfix__`.
+
+    This is useful in combination with the `extends` function to
+    implement deep overriding.
+  */
   fix' = f: let x = f x // { __unfix__ = f; }; in x;
 
-  # Return the fixpoint that `f` converges to when called recursively, starting
-  # with the input `x`.
-  #
-  #     nix-repl> converge (x: x / 2) 16
-  #     0
+  /*
+    Return the fixpoint that `f` converges to when called iteratively, starting
+    with the input `x`.
+
+    ```
+    nix-repl> converge (x: x / 2) 16
+    0
+    ```
+
+    Type: (a -> a) -> a -> a
+  */
   converge = f: x:
     let
       x' = f x;
@@ -37,75 +52,94 @@ rec {
       then x
       else converge f x';
 
-  # Modify the contents of an explicitly recursive attribute set in a way that
-  # honors `self`-references. This is accomplished with a function
-  #
-  #     g = self: super: { foo = super.foo + " + "; }
-  #
-  # that has access to the unmodified input (`super`) as well as the final
-  # non-recursive representation of the attribute set (`self`). `extends`
-  # differs from the native `//` operator insofar as that it's applied *before*
-  # references to `self` are resolved:
-  #
-  #     nix-repl> fix (extends g f)
-  #     { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; }
-  #
-  # The name of the function is inspired by object-oriented inheritance, i.e.
-  # think of it as an infix operator `g extends f` that mimics the syntax from
-  # Java. It may seem counter-intuitive to have the "base class" as the second
-  # argument, but it's nice this way if several uses of `extends` are cascaded.
-  #
-  # To get a better understanding how `extends` turns a function with a fix
-  # point (the package set we start with) into a new function with a different fix
-  # point (the desired packages set) lets just see, how `extends g f`
-  # unfolds with `g` and `f` defined above:
-  #
-  # extends g f = self: let super = f self; in super // g self super;
-  #             = self: let super = { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }; in super // g self super
-  #             = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // g self { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
-  #             = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // { foo = "foo" + " + "; }
-  #             = self: { foo = "foo + "; bar = "bar"; foobar = self.foo + self.bar; }
-  #
+  /*
+    Modify the contents of an explicitly recursive attribute set in a way that
+    honors `self`-references. This is accomplished with a function
+
+    ```nix
+    g = self: super: { foo = super.foo + " + "; }
+    ```
+
+    that has access to the unmodified input (`super`) as well as the final
+    non-recursive representation of the attribute set (`self`). `extends`
+    differs from the native `//` operator insofar as that it's applied *before*
+    references to `self` are resolved:
+
+    ```
+    nix-repl> fix (extends g f)
+    { bar = "bar"; foo = "foo + "; foobar = "foo + bar"; }
+    ```
+
+    The name of the function is inspired by object-oriented inheritance, i.e.
+    think of it as an infix operator `g extends f` that mimics the syntax from
+    Java. It may seem counter-intuitive to have the "base class" as the second
+    argument, but it's nice this way if several uses of `extends` are cascaded.
+
+    To get a better understanding how `extends` turns a function with a fix
+    point (the package set we start with) into a new function with a different fix
+    point (the desired packages set) lets just see, how `extends g f`
+    unfolds with `g` and `f` defined above:
+
+    ```
+    extends g f = self: let super = f self; in super // g self super;
+                = self: let super = { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }; in super // g self super
+                = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // g self { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; }
+                = self: { foo = "foo"; bar = "bar"; foobar = self.foo + self.bar; } // { foo = "foo" + " + "; }
+                = self: { foo = "foo + "; bar = "bar"; foobar = self.foo + self.bar; }
+    ```
+  */
   extends = f: rattrs: self: let super = rattrs self; in super // f self super;
 
-  # Compose two extending functions of the type expected by 'extends'
-  # into one where changes made in the first are available in the
-  # 'super' of the second
+  /*
+    Compose two extending functions of the type expected by 'extends'
+    into one where changes made in the first are available in the
+    'super' of the second
+  */
   composeExtensions =
     f: g: final: prev:
       let fApplied = f final prev;
           prev' = prev // fApplied;
       in fApplied // g final prev';
 
-  # Compose several extending functions of the type expected by 'extends' into
-  # one where changes made in preceding functions are made available to
-  # subsequent ones.
-  #
-  # composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
-  #                          ^final        ^prev         ^overrides     ^final        ^prev         ^overrides
+  /*
+    Compose several extending functions of the type expected by 'extends' into
+    one where changes made in preceding functions are made available to
+    subsequent ones.
+
+    ```
+    composeManyExtensions : [packageSet -> packageSet -> packageSet] -> packageSet -> packageSet -> packageSet
+                              ^final        ^prev         ^overrides     ^final        ^prev         ^overrides
+    ```
+  */
   composeManyExtensions =
     lib.foldr (x: y: composeExtensions x y) (final: prev: {});
 
-  # Create an overridable, recursive attribute set. For example:
-  #
-  #     nix-repl> obj = makeExtensible (self: { })
-  #
-  #     nix-repl> obj
-  #     { __unfix__ = «lambda»; extend = «lambda»; }
-  #
-  #     nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
-  #
-  #     nix-repl> obj
-  #     { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
-  #
-  #     nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
-  #
-  #     nix-repl> obj
-  #     { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
+  /*
+    Create an overridable, recursive attribute set. For example:
+
+    ```
+    nix-repl> obj = makeExtensible (self: { })
+
+    nix-repl> obj
+    { __unfix__ = «lambda»; extend = «lambda»; }
+
+    nix-repl> obj = obj.extend (self: super: { foo = "foo"; })
+
+    nix-repl> obj
+    { __unfix__ = «lambda»; extend = «lambda»; foo = "foo"; }
+
+    nix-repl> obj = obj.extend (self: super: { foo = super.foo + " + "; bar = "bar"; foobar = self.foo + self.bar; })
+
+    nix-repl> obj
+    { __unfix__ = «lambda»; bar = "bar"; extend = «lambda»; foo = "foo + "; foobar = "foo + bar"; }
+    ```
+  */
   makeExtensible = makeExtensibleWithCustomName "extend";
 
-  # Same as `makeExtensible` but the name of the extending attribute is
-  # customized.
+  /*
+    Same as `makeExtensible` but the name of the extending attribute is
+    customized.
+  */
   makeExtensibleWithCustomName = extenderName: rattrs:
     fix' (self: (rattrs self) // {
       ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs);