Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few more steps in explaining the use of fix in Nix overrides #228

Conversation

why-not-try-calmer
Copy link

@why-not-try-calmer why-not-try-calmer commented Feb 9, 2024

After coming back to Nix I absolutely loved the Nix pills! However I felt like the part on fix was a bit dense to digest. Here's an attempt to expound it a little bit.

@@ -51,23 +51,20 @@
</para>
<screen><xi:include href="./17/fix-function.txt" parse="text" /></screen>
<para>
It's a function that accepts a function <literal>f</literal>, calls <literal>f result</literal> on the result just returned by <literal>f result</literal> and returns it. In other words it's <literal>f(f(f(....</literal>
It's a function that accepts a function <literal>f</literal> and returns a function that recurses over f's arguments. Why is this useful? Because it plays nicely with Nix' laziness: it turns any function that otherwise would happily return (at least some) of its arguments unevaluated, into a function that recursively evaluates its arguments until there is nothing left to evaluate. To fix ideas (pun intended!) consider:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

returns a function that recurses over f's arguments

It does not necessarily return a function:

nix-repl> lib.fix (lib.const "foo")
"foo"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. It does so just in case it is given a function. I think this is the case we're interested in anyway. I hope this is clear enough in the text.

pills/17/fix-function-sum.txt Outdated Show resolved Hide resolved
pills/17-nixpkgs-overriding-packages.xml Outdated Show resolved Hide resolved
pills/17/fix-function-sum.txt Outdated Show resolved Hide resolved
pills/17/fix-function-sum.txt Outdated Show resolved Hide resolved
@@ -44,31 +44,20 @@
<section>
<title>Fixed point</title>
<para>
The fixed point with lazy evaluation is crippling but about necessary in a language like Nix. It lets us achieve something similar to what we'd do imperatively.
A fixed point is a common pattern in lazy languages to ensure that functions that would otherwise return non fully evaluated values do return fully evaluated values. Let's unpack this idea. Remember that in Nix functions are lazy. Consider:
Copy link
Member

@jtojnar jtojnar Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A fixed point is a common pattern in lazy languages to ensure that functions that would otherwise return non fully evaluated values do return fully evaluated values.

I am not sure that forcing strict evaluation (i.e. builtins.seq) has anything to do with fixed point.

But even if it had, I believe the main purpose of fix point operators in functional languages is facilitating (mutual) recursion when the language lacks support for expressing it explicitly (see https://en.wikipedia.org/wiki/Let_expression).

Now, this is not a problem in Nix, since its let expression is a let-rec, so the primary purpose it to allow extensibility of attribute sets (essentially late binding). In my understanding, this is also the motivation for this section, since pkgs heavily relay on fixed-point for overlays and other extension mechanisms.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to imply anything about seq. But all you said about let-rec is correct. I've boiled it down to minimize jargon.

pills/17-nixpkgs-overriding-packages.xml Outdated Show resolved Hide resolved
</para>
<screen><xi:include href="./17/fix-function.txt" parse="text" /></screen>
<literal>How does this related to <literal>fix</literal>? Well it is a function that takes a function f into function g such that g recursively calls f until f can no longer evaluate its arguments. Or in other words: until all thunks have been replaced by the actual values. Consider:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

takes a function f into function g

I do not understand what this means.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be more understandable now.

@roberth
Copy link
Member

roberth commented Feb 14, 2024

lib.fix itself already has a fairly decent explanation in its reference documentation if I may say so.

Just fyi; in case it helps. Or maybe it could be linked to?

@jtojnar
Copy link
Member

jtojnar commented Feb 15, 2024

lib.fix itself already has a fairly decent explanation in its reference documentation if I may say so.

We already link an older version. Might be a good idea to update it.

Should be more understandable now.

To be honest, I still find the original version more focused and understandable. People should not really need to care about what a fix point actually is unless they want to.

@why-not-try-calmer
Copy link
Author

why-not-try-calmer commented Feb 15, 2024

lib.fix itself already has a fairly decent explanation in its reference documentation if I may say so.

We already link an older version. Might be a good idea to update it.

Should be more understandable now.

To be honest, I still find the original version more focused and understandable. People should not really need to care about what a fix point actually is unless they want to.

Got it. Thank you all for helping improve this, even if it didn't pan out as I wanted at the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

4 participants