or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mdcontainer-methods.mdcontext-operations.mdconversions.mdcore-containers.mddevelopment-tools.mdfunctional-utilities.mdindex.mditeration-utilities.mdpointfree.mdtrampolines.mdunsafe-operations.md

trampolines.mddocs/

0

# Trampolines

1

2

Tail-call optimization utilities that convert recursive functions into iterative ones to avoid stack overflow errors. This enables safe recursion in Python for functional programming patterns.

3

4

## Capabilities

5

6

### Trampoline Container

7

8

A container that represents a computation step in a recursive algorithm, enabling tail-call optimization.

9

10

```python { .api }

11

class Trampoline[T]:

12

"""Container for tail-call optimized recursion"""

13

def __init__(self, computation: Callable[[], Trampoline[T] | T]): ...

14

15

def run(self) -> T:

16

"""Execute the trampoline until completion"""

17

18

def bind(self, func: Callable[[T], Trampoline[U]]) -> Trampoline[U]:

19

"""Bind a function returning Trampoline"""

20

21

def map(self, func: Callable[[T], U]) -> Trampoline[U]:

22

"""Transform the final result"""

23

24

@classmethod

25

def done(cls, value: T) -> Trampoline[T]:

26

"""Create a completed trampoline"""

27

28

@classmethod

29

def call(cls, func: Callable[[], Trampoline[T] | T]) -> Trampoline[T]:

30

"""Create a trampoline from a thunk"""

31

```

32

33

### Trampoline Decorator

34

35

Convert recursive functions to use trampolines automatically.

36

37

```python { .api }

38

def trampoline(func: Callable[..., Trampoline[T]]) -> Callable[..., T]:

39

"""Convert trampoline-returning function to regular function"""

40

```

41

42

## Usage Examples

43

44

### Basic Tail Recursion

45

46

```python

47

from returns.trampolines import Trampoline, trampoline

48

49

# Traditional recursive factorial (stack overflow risk)

50

def factorial_recursive(n: int, acc: int = 1) -> int:

51

if n <= 1:

52

return acc

53

return factorial_recursive(n - 1, acc * n)

54

55

# Trampoline version (stack safe)

56

def factorial_trampoline(n: int, acc: int = 1) -> Trampoline[int]:

57

if n <= 1:

58

return Trampoline.done(acc)

59

return Trampoline.call(lambda: factorial_trampoline(n - 1, acc * n))

60

61

@trampoline

62

def factorial(n: int) -> Trampoline[int]:

63

return factorial_trampoline(n)

64

65

# Safe for large numbers

66

result = factorial(10000) # No stack overflow

67

```

68

69

### Mutual Recursion

70

71

```python

72

from returns.trampolines import Trampoline, trampoline

73

74

def is_even_trampoline(n: int) -> Trampoline[bool]:

75

if n == 0:

76

return Trampoline.done(True)

77

return Trampoline.call(lambda: is_odd_trampoline(n - 1))

78

79

def is_odd_trampoline(n: int) -> Trampoline[bool]:

80

if n == 0:

81

return Trampoline.done(False)

82

return Trampoline.call(lambda: is_even_trampoline(n - 1))

83

84

@trampoline

85

def is_even(n: int) -> Trampoline[bool]:

86

return is_even_trampoline(n)

87

88

@trampoline

89

def is_odd(n: int) -> Trampoline[bool]:

90

return is_odd_trampoline(n)

91

92

# Safe for large numbers

93

result = is_even(100000) # True, no stack overflow

94

```

95

96

### List Processing

97

98

```python

99

from returns.trampolines import Trampoline, trampoline

100

from typing import List

101

102

def sum_list_trampoline(items: List[int], acc: int = 0) -> Trampoline[int]:

103

if not items:

104

return Trampoline.done(acc)

105

return Trampoline.call(

106

lambda: sum_list_trampoline(items[1:], acc + items[0])

107

)

108

109

@trampoline

110

def sum_list(items: List[int]) -> Trampoline[int]:

111

return sum_list_trampoline(items)

112

113

# Process large lists safely

114

large_list = list(range(50000))

115

total = sum_list(large_list) # No stack overflow

116

```

117

118

### Trampoline with Container Integration

119

120

```python

121

from returns.trampolines import Trampoline, trampoline

122

from returns.result import Result, Success, Failure

123

from returns.maybe import Maybe, Some, Nothing

124

125

def safe_divide_recursive(

126

dividend: float,

127

divisor: float,

128

depth: int = 0

129

) -> Trampoline[Result[float, str]]:

130

if depth > 100:

131

return Trampoline.done(Failure("Maximum recursion depth reached"))

132

133

if divisor == 0:

134

return Trampoline.done(Failure("Division by zero"))

135

136

if dividend < 1:

137

return Trampoline.done(Success(dividend))

138

139

# Continue dividing

140

return Trampoline.call(

141

lambda: safe_divide_recursive(dividend / divisor, divisor, depth + 1)

142

)

143

144

@trampoline

145

def safe_divide_until_small(dividend: float, divisor: float) -> Trampoline[Result[float, str]]:

146

return safe_divide_recursive(dividend, divisor)

147

148

# Safe recursive division

149

result = safe_divide_until_small(1000000.0, 2.0) # Success(small_number)

150

```

151

152

## Performance Benefits

153

154

Trampolines provide several advantages for recursive algorithms:

155

156

1. **Stack Safety**: Eliminates stack overflow errors for deep recursion

157

2. **Memory Efficiency**: Uses constant stack space regardless of recursion depth

158

3. **Composability**: Works with other functional programming constructs

159

4. **Debugging**: Easier to debug than traditional recursion

160

161

## When to Use Trampolines

162

163

Use trampolines when:

164

165

- Implementing naturally recursive algorithms (factorial, fibonacci, tree traversal)

166

- Processing large data structures recursively

167

- Converting imperative loops to functional style

168

- Implementing recursive descent parsers

169

- Working with recursive data structures (linked lists, trees)

170

171

Trampolines enable safe functional programming patterns that would otherwise be limited by Python's recursion depth limit.