Skip to content

Instantly share code, notes, and snippets.

@hurryabit
Last active January 8, 2022 17:16
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hurryabit/a7213d9c8d059c31f51686bd66691592 to your computer and use it in GitHub Desktop.
Save hurryabit/a7213d9c8d059c31f51686bd66691592 to your computer and use it in GitHub Desktop.
Stack-safety for free?
# This gist contains the Python version of the code from the blog post
# https://hurryabit.github.io/blog/stack-safety-for-free/
import sys
from typing import Callable, Generator, TypeVar
Arg = TypeVar("Arg")
Res = TypeVar("Res")
def triangular(n: int) -> int:
if n == 0:
return 0
else:
return n + triangular(n - 1)
def trampoline(f: Callable[[Arg], Generator[Arg, Res, Res]]) -> Callable[[Arg], Res]:
def mu_f(arg: Arg) -> Res:
stack = []
current = f(arg)
res: B = None # type: ignore
while True:
try:
arg = current.send(res)
stack.append(current)
current = f(arg)
res = None # type: ignore
except StopIteration as stop:
if len(stack) > 0:
current = stack.pop()
res = stop.value
else:
return stop.value
return mu_f
@trampoline
def triangular_safe(n: int) -> Generator[int, int, int]:
if n == 0:
return 0
else:
return n + (yield (n - 1))
LARGE: int = sys.getrecursionlimit() + 1
assert triangular_safe(LARGE) == LARGE * (LARGE + 1) // 2
print("`triangular_safe` has not overflowed its stack.")
print("`triangular` will overflow its stack soon...")
try:
triangular(LARGE)
raise Exception("`triangular` has not overflowed its stack.")
except RecursionError:
print("`triangular` has overflowed its stack.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment