mutual_recursion/README.md

64 lines
1.3 KiB
Markdown
Raw Permalink Normal View History

2019-01-26 14:41:19 -05:00
# Mutual Recursion
2019-01-27 13:34:26 -05:00
Tail call optimization for mutually (indirectly) and directly recursive functions in Ruby.
2019-01-26 14:41:19 -05:00
2019-01-27 13:34:26 -05:00
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.
2019-01-27 11:55:52 -05:00
2019-01-26 14:41:19 -05:00
### examples
```ruby
require 'mutual_recursion'
2019-01-27 11:55:52 -05:00
include MutualRecursion
2019-01-26 14:41:19 -05:00
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'
2019-01-27 11:55:52 -05:00
include MutualRecursion
2019-01-26 14:41:19 -05:00
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'
2019-01-27 11:55:52 -05:00
include MutualRecursion
2019-01-26 14:41:19 -05:00
def proc_returning(x, y = 0)
return terminal_value(proc { "|#{y}|" }) if x.negative?
tail_call { proc_returning(x - 1, y + 1) }
end
2019-01-27 11:55:52 -05:00
generated_proc = proc_returning(20).invoke
generated_proc.call
2019-01-26 14:41:19 -05:00
# => "|21|"
```
2019-01-27 11:55:52 -05:00
```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
```