examples/functions/04_tail_recursion.cat
# Tail Recursion Examples
# ======================
# Demonstrates automatic tail-call optimization in Catnip
# Basic tail recursion: factorial
# --------------------------------
# All recursive calls are in tail position (last operation)
factorial = (n, acc=1) => {
if n <= 1 { acc }
else { factorial(n - 1, n * acc) }
}
print("factorial(5) =", factorial(5)) # 120
print("factorial(10) =", factorial(10)) # 3628800
# Can handle deep recursion without stack overflow
print("factorial(100) digits:", len(str(factorial(100)))) # 158 digits
# Countdown example
# -----------------
countdown = (n) => {
if n == 0 {
print("Liftoff!")
"Done"
} else {
print(n)
countdown(n - 1) # Tail call
}
}
countdown(5)
# Sum from 1 to N (tail recursive)
# ---------------------------------
sum_to = (n, acc=0) => {
if n == 0 { acc }
else { sum_to(n - 1, acc + n) }
}
print("\nsum_to(100) =", sum_to(100)) # 5050
print("sum_to(1000) =", sum_to(1000)) # 500500
# Range sum (tail recursive)
# ---------------------------
range_sum = (start, end, acc=0) => {
if start > end { acc }
else { range_sum(start + 1, end, acc + start) } # Tail call
}
print("\nrange_sum(1, 10) =", range_sum(1, 10, 0)) # 55
print("range_sum(50, 100) =", range_sum(50, 100, 0)) # 3825
# GCD (greatest common divisor) - Euclidean algorithm
# ----------------------------------------------------
gcd = (a, b) => {
if b == 0 { a }
else { gcd(b, a % b) } # Tail call
}
print("\ngcd(48, 18) =", gcd(48, 18)) # 6
print("gcd(1071, 462) =", gcd(1071, 462)) # 21
# Power function (tail recursive)
# --------------------------------
power = (base, exp, acc=1) => {
if exp == 0 { acc }
else { power(base, exp - 1, acc * base) }
}
print("\npower(2, 10) =", power(2, 10)) # 1024
print("power(3, 5) =", power(3, 5)) # 243
# Comparison: Non-tail vs Tail recursive
# ---------------------------------------
# Non-tail: recursive call NOT in final position
fib_non_tail = (n) => {
if n <= 1 { n }
else {
fib_non_tail(n - 1) + fib_non_tail(n - 2) # Addition after calls
}
}
# Tail-recursive version with accumulator
fib_tail = (n, a=0, b=1) => {
if n == 0 { a }
else { fib_tail(n - 1, b, a + b) } # Tail call
}
print("\n--- Fibonacci Comparison ---")
print("Non-tail fib(10):", fib_non_tail(10)) # Slow, exponential time
print("Tail fib(10):", fib_tail(10)) # Fast, linear time
print("Tail fib(100):", fib_tail(100)) # Works for large N!
# How it works
# ------------
# Catnip automatically transforms tail-recursive functions into while loops:
#
# factorial = (n, acc=1) => {
# if n <= 1 { acc }
# else { factorial(n - 1, n * acc) }
# }
#
# Becomes (conceptually):
#
# factorial = (n, acc=1) => {
# while true {
# if n <= 1 { return acc }
# tmp_0 = n - 1
# tmp_1 = n * acc
# n = tmp_0
# acc = tmp_1
# }
# }
#
# Benefits:
# - O(1) stack space (no stack overflow)
# - Near-native loop performance
# - No manual conversion needed