Tried to derive the Z combinator and instead derived another I was working to derive the Z-Combinator by starting with the factorial function and ended up deriving a different fixed-point combinator. What did I derive? Did I make a subtle mistake?
Here are the steps I performed (in JavaScript)
1. Declare factorial function
let fact = n =&gt;
    n &lt; 2 ? 1 : n * fact(n - 1)

2. Convert to combinator (closed expression)
let fact = (self, n) =&gt;
    n &lt; 2 ? 1 : n * self(n - 1)

3. Thread self call
Based on signature fact(?, 7), passing fact as first argument seems reasonable fact(fact,7). So thread the parameter through the tail call:
let fact = (self, n) =&gt;
    n &lt; 2 ? 1 : n * self(self, n - 1)

Usage is now fact(fact,7) → 5040
4. Refactor to curried form
let fact = self =&gt;
    n =&gt; n &lt; 2 ? 1 : n * self(self)(n - 1)

5. Move self application to local declaration
let fact = self =&gt; {
    let f = n =&gt; self(self)(n)
    return n =&gt; n &lt; 2 ? 1 : n * f(n - 1)
}

6. Convert let declaration to lambda expression
let fact = self =&gt;
    (f =&gt;
        n =&gt; n &lt; 2 ? 1 : n * f(n - 1)
    )(
        n =&gt; self(self)(n)
    )

Usage is still fact(fact)(7) → 5040
7. Separate the factorial expression
let _fact = f =&gt; n =&gt;
    n &lt; 2 ? 1 : n * f(n - 1)

let fact = self =&gt;
    (
        _fact
    )(
        n =&gt; self(self)(n)
    )

8. Move self-application from caller to body
let _fact =
    f =&gt; n =&gt; n &lt; 2 ? 1 : n * f(n - 1)

let fact = (() =&gt; {
    let innerFact = self =&gt;
        (
            _fact
        )(
            n =&gt; self(self)(n)
        )
    return innerFact(innerFact)
})()

Usage is now fact(7) → 5040
9. Convert let declaration to lambda expression
let _fact =
    f =&gt; n =&gt; n &lt; 2 ? 1 : n * f(n - 1)

let fact = (() =&gt; {
    return (
        innerFact =&gt; innerFact(innerFact)
    )(
        self =&gt; (_fact)(n =&gt; self(self)(n))
    )
})()

10. Simplify expression
let _fact =
    f =&gt; n =&gt; n &lt; 2 ? 1 : n * f(n - 1)

let fact =
    (innerFact =&gt; innerFact(innerFact))
    (self =&gt; (_fact)(n =&gt; self(self)(n)))

Sanity check. Usage is still fact(7) → 5040
11. Rename variables
The usage of innerFact and self look suspiciously similar. Rename to the same variable to discover a pattern. Separate lexical scopes so safe to do:
let _fact =
    f =&gt; n =&gt; n &lt; 2 ? 1 : n * f(n - 1)

let fact =
    (u =&gt; u(u))
    (u =&gt; (_fact)(n =&gt; u(u)(n)))

12. Abstract _fact usage and rename fact
Rename fact to setup and abstract _fact in body by replacing with parameter f
let _fact =
    f =&gt; n =&gt; n &lt; 2 ? 1 : n * f(n - 1)

let setup = f =&gt;
    (u =&gt; u(u))
    (u =&gt; (f)(n =&gt; u(u)(n)))

let fact = setup(_fact)

No need for separate _fact declaration so inline:
let setup = f =&gt;
    (u =&gt; u(u))
    (u =&gt; (f)(n =&gt; u(u)(n)))

let fact = setup(
    f =&gt; n =&gt; n &lt; 2 ? 1 : n * f(n - 1)
)

13. Rename setup
Rename it to what? What combinator is this? According to Wikipedia The Z combinator is:
let Z = f =&gt; 
    (u =&gt; f(v =&gt; u(u)(v)))
    (u =&gt; f(v =&gt; u(u)(v)))

But what I've derived is:
let setup = f =&gt;
    (u =&gt; u(u))
    (u =&gt; (f)(n =&gt; u(u)(n)))

Defining fact in terms of either seems equivalent in behavior. Did I make a mistake? Did I accidentally rediscover another well-known combinator?
If I inline (u =&gt; (f)(n =&gt; u(u)(n))) into (u =&gt; u(u)) I get:
(u =&gt; f(n =&gt; u(u)(n)))
(u =&gt; f(n =&gt; u(u)(n)))

Which is exactly the Z-Combinator.
From wikipedia:
let Z = f =&gt; 
    (u =&gt; f(v =&gt; u(u)(v)))
    (u =&gt; f(v =&gt; u(u)(v)))

My derivation:
let fix = f =&gt;
    (u =&gt; f(n =&gt; u(u)(n)))
    (u =&gt; f(n =&gt; u(u)(n)))