Skip to content

Instantly share code, notes, and snippets.

@iGoodie
Last active July 9, 2024 14:03
Show Gist options
  • Save iGoodie/172c605282882f168bcac1d3c53f6737 to your computer and use it in GitHub Desktop.
Save iGoodie/172c605282882f168bcac1d3c53f6737 to your computer and use it in GitHub Desktop.
type NotFunction =
| string
| number
| boolean
| null
| undefined
| bigint
| readonly any[]
| { apply?: never; [k: string]: any }
| { call?: never; [k: string]: any };
export type Trampoline<T extends NotFunction> = T | (() => Trampoline<T>);
export type TrampolineFunc<A extends any[], T extends NotFunction> = (
...args: A
) => Trampoline<T>;
export function trampoline<A extends any[], T extends NotFunction>(
fn: TrampolineFunc<A, T>
) {
return (...args: A) => {
let result = fn(...args);
while (typeof result === "function") {
result = result();
}
return result;
};
}
/* -------------------------- */
function factorialImpl(n: number, prev: number = 1): Trampoline<number> {
if (n < 2) return prev;
return () => factorialImpl(n - 1, prev * n);
}
const factorial = trampoline(factorialImpl);
console.log(factorial(1000));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment