Tail-call optimization for Ruby
Go to file
Mike Cifelli 0adb914ac7 Increment version 2019-01-27 14:30:45 -05:00
.vscode Move functions into module 2019-01-27 11:55:52 -05:00
lib Move functions into module 2019-01-27 11:55:52 -05:00
test Updates for initial release 2019-01-27 13:34:26 -05:00
.gitignore Move functions into module 2019-01-27 11:55:52 -05:00
LICENSE Add LICENSE 2019-01-27 19:09:06 +00:00
README.md Updates for initial release 2019-01-27 13:34:26 -05:00
Rakefile Use rake to run tests 2019-01-26 15:10:05 -05:00
mutual_recursion.gemspec Increment version 2019-01-27 14:30:45 -05:00

README.md

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

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
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
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|"
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