Ruby で。相互再帰に対応

まぁほとんどそのまま

module LOOP_EX
  class Clusure
    # wrapper object
    attr_reader :func
    attr_reader :args

    def initialize f, v
      @func = f
      @args = v
    end
  end

  def loop_ex func
    private_name = (" " + func.to_s).to_sym

    # original method is callable by private_name
    alias_method private_name, func

    # redefine original name by wrapping method
    define_method func, lambda {|*args|
      Clusure.new private_name, args
    }
    # this method should not use from external
    private func

    # interface for external
    define_method func.to_s + "_loop", lambda {|*args|
      r = Clusure.new private_name, args
      while r.kind_of? Clusure do
        r = __send__ r.func, *r.args
      end
      r
    }
  end
end

class Foo
  extend LOOP_EX

  def even n
    if n == 0 then
      true
    else
      odd(n - 1)
    end
  end

  def odd n
    if n == 0 then
      false
    else
      even(n - 1)
    end
  end

  loop_ex :even
  loop_ex :odd
end

foo = Foo.new
(0 .. 10).each {|i|
  puts "#{i} is even? ... #{foo.even_loop i}"
}
(0 .. 10).each {|i|
  puts "#{i} is odd? ... #{foo.odd_loop i}"
}