Update readme

This commit is contained in:
Mike Cifelli 2019-01-26 14:41:19 -05:00
parent caf0a7c80c
commit 5959e9dc8d
3 changed files with 52 additions and 4 deletions

View File

@ -0,0 +1,46 @@
# Mutual Recursion
Tail call optimization for mutually (and directly) recursive functions in Ruby.
The current desing uses a trampoline. However, it is implemented in a way that still allows a tail recursive function to return a Proc as its terminal value without it being called prematurely by accident.
### examples
```ruby
require 'mutual_recursion'
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'
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'
def proc_returning(x, y = 0)
return terminal_value(proc { "|#{y}|" }) if x.negative?
tail_call { proc_returning(x - 1, y + 1) }
end
proc_returning(20).invoke.call
# => "|21|"
```

View File

@ -8,6 +8,6 @@ Gem::Specification.new do |s|
s.description = 'Tail call optimization for mutually (and directly) recursive functions using a trampoline.' s.description = 'Tail call optimization for mutually (and directly) recursive functions using a trampoline.'
s.authors = ['Mike'] s.authors = ['Mike']
s.files = ['lib/mutual_recursion.rb'] s.files = ['lib/mutual_recursion.rb']
s.homepage = '' s.homepage = 'https://gitlab.com/mike-cifelli/mutual_recursion'
s.license = 'MIT' s.license = 'MIT'
end end

View File

@ -37,7 +37,7 @@ class InventoryTest < Minitest::Test
end end
def test_recursive_function_can_return_proc def test_recursive_function_can_return_proc
tail = proc_returning tail = proc_returning(20)
assert_kind_of(Proc, tail.invoke) assert_kind_of(Proc, tail.invoke)
end end
@ -76,8 +76,10 @@ def lambda_returning
terminal_value(-> { 24 }) terminal_value(-> { 24 })
end end
def proc_returning def proc_returning(x, y = 0)
terminal_value(proc { 24 }) return terminal_value(proc { puts "|#{y}|" }) if x.negative?
tail_call { proc_returning(x - 1, y + 1) }
end end
def bad_return def bad_return