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 =>
n < 2 ? 1 : n * fact(n - 1)
```

## 2. Convert to combinator (closed expression)

```
let fact = (self, n) =>
n < 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) =>
n < 2 ? 1 : n * self(self, n - 1)
```

Usage is now `fact(fact,7)`

→ `5040`

## 4. Refactor to curried form

```
let fact = self =>
n => n < 2 ? 1 : n * self(self)(n - 1)
```

## 5. Move self application to local declaration

```
let fact = self => {
let f = n => self(self)(n)
return n => n < 2 ? 1 : n * f(n - 1)
}
```

## 6. Convert let declaration to lambda expression

```
let fact = self =>
(f =>
n => n < 2 ? 1 : n * f(n - 1)
)(
n => self(self)(n)
)
```

Usage is still `fact(fact)(7)`

→ `5040`

## 7. Separate the factorial expression

```
let _fact = f => n =>
n < 2 ? 1 : n * f(n - 1)
let fact = self =>
(
_fact
)(
n => self(self)(n)
)
```

## 8. Move self-application from caller to body

```
let _fact =
f => n => n < 2 ? 1 : n * f(n - 1)
let fact = (() => {
let innerFact = self =>
(
_fact
)(
n => self(self)(n)
)
return innerFact(innerFact)
})()
```

Usage is now `fact(7)`

→ `5040`

## 9. Convert let declaration to lambda expression

```
let _fact =
f => n => n < 2 ? 1 : n * f(n - 1)
let fact = (() => {
return (
innerFact => innerFact(innerFact)
)(
self => (_fact)(n => self(self)(n))
)
})()
```

## 10. Simplify expression

```
let _fact =
f => n => n < 2 ? 1 : n * f(n - 1)
let fact =
(innerFact => innerFact(innerFact))
(self => (_fact)(n => 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 => n => n < 2 ? 1 : n * f(n - 1)
let fact =
(u => u(u))
(u => (_fact)(n => 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 => n => n < 2 ? 1 : n * f(n - 1)
let setup = f =>
(u => u(u))
(u => (f)(n => u(u)(n)))
let fact = setup(_fact)
```

No need for separate `_fact`

declaration so inline:

```
let setup = f =>
(u => u(u))
(u => (f)(n => u(u)(n)))
let fact = setup(
f => n => n < 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 =>
(u => f(v => u(u)(v)))
(u => f(v => u(u)(v)))
```

But what I’ve derived is:

```
let setup = f =>
(u => u(u))
(u => (f)(n => 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?