継続で末尾再帰

ライブドアブログ(livedoor Blog)| 読みたいブログが見つかるより。
letを改造すると継続で末尾再帰がもう少しシンプルに書けるような気がします。こんな感じ。

module Let
  def _set_scope_accessor(scope, assigns)
    assigns.each do |name, value|
      scope.instance_eval("def #{name}; @#{name} end")
    end
  end

  def _set_scope_value(scope, assigns)
    assigns.each do |name, value|
      scope.instance_variable_set("@#{name}", value)
    end
  end

  def reclet(assigns = {}, &block)
    scope = Object.new
    _set_scope_accessor(scope, assigns)
    _set_scope_value(scope, assigns)

    scope.instance_eval(
      'def reccall(assigns = {}); _set_scope_value(self, assigns); @cc[] end')
    cc = nil
    callcc {|i| cc = i }
    scope.instance_variable_set('@cc', cc)
    
    scope.instance_eval(&block)
  end
end

include Let

def sum(num)
  reclet :n => num, :acc => 0 do
    if n == 0
      acc
    else
      reccall :n => n - 1, :acc => acc + n
    end
  end
end

p sum(1000)  # => 500500
p sum(10000) # => 50005000

ほう。常用はしないと思いますが、ネタとしてはなかなか興味深いです。
参照: jijixi’s diary