mutual_recursion/lib/mutual_recursion.rb

34 lines
615 B
Ruby

# frozen_string_literal: true
module MutualRecursion
UNEXPECTED_TYPE = 'expected tail_call or terminal_value'
class TailCall
attr_reader :value, :block
def initialize(value = nil, &block)
@value = value
@block = block
end
def invoke
self.then do |tail|
while tail.block
tail = tail.block.call
raise TypeError, UNEXPECTED_TYPE unless tail.is_a?(TailCall)
end
tail.value
end
end
end
end
def tail_call
MutualRecursion::TailCall.new { yield }
end
def terminal_value(value)
MutualRecursion::TailCall.new(value)
end