64 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			64 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# Mutual Recursion
 | 
						|
 | 
						|
Tail call optimization for mutually (indirectly) and directly recursive functions in Ruby.
 | 
						|
 | 
						|
The current design uses a trampoline. However, it is implemented in a way that still allows a tail recursive function to easily return a Proc as its terminal value.
 | 
						|
 | 
						|
### examples
 | 
						|
```ruby
 | 
						|
require 'mutual_recursion'
 | 
						|
include MutualRecursion
 | 
						|
 | 
						|
def mutual_one(x, y = 0)
 | 
						|
  return terminal_value(y) if x.negative?
 | 
						|
 | 
						|
  tail_call { mutual_two(x, y + 1) }
 | 
						|
end
 | 
						|
 | 
						|
def mutual_two(x, y)
 | 
						|
  tail_call { mutual_one(x - 1, y) }
 | 
						|
end
 | 
						|
 | 
						|
mutual_one(50_000).invoke
 | 
						|
# => 50001
 | 
						|
```
 | 
						|
```ruby
 | 
						|
require 'mutual_recursion'
 | 
						|
include MutualRecursion
 | 
						|
 | 
						|
def direct(x, y = 0)
 | 
						|
  return terminal_value(y) if x.negative?
 | 
						|
 | 
						|
  tail_call { direct(x - 1, y + 1) }
 | 
						|
end
 | 
						|
 | 
						|
direct(50_000).invoke
 | 
						|
# => 50001
 | 
						|
```
 | 
						|
```ruby
 | 
						|
require 'mutual_recursion'
 | 
						|
include MutualRecursion
 | 
						|
 | 
						|
def proc_returning(x, y = 0)
 | 
						|
  return terminal_value(proc { "|#{y}|" }) if x.negative?
 | 
						|
 | 
						|
  tail_call { proc_returning(x - 1, y + 1) }
 | 
						|
end
 | 
						|
 | 
						|
generated_proc = proc_returning(20).invoke
 | 
						|
generated_proc.call
 | 
						|
# => "|21|"
 | 
						|
```
 | 
						|
```ruby
 | 
						|
require 'mutual_recursion'
 | 
						|
 | 
						|
def without_include(x, y = 0)
 | 
						|
  return MutualRecursion.terminal_value(y) if x.negative?
 | 
						|
 | 
						|
  MutualRecursion.tail_call { without_include(x - 1, y + 1) }
 | 
						|
end
 | 
						|
 | 
						|
without_include(50_000).invoke
 | 
						|
# => 50001
 | 
						|
```
 |