Hash でお手軽にメモ化 で書いた Hash
を用いたメモ化が結構気に入ったので,メタプログラミングの練習がてら,もう少し簡単にわかりやすく書けるモジュールを作ってみた.
こんな風に使える.
# ブロックを与えて呼び出すと,Memo のスコープ内にブロックで指定したメソッドを生成する Memo.fib do |n| if n < 2 1 else Memo.fib(n-1) + Memo.fib(n-2) end end # 生成した後は普通に呼び出して使える. # 処理はメモ化されているので,フィボナッチ数列1000 項目も一瞬で計算できる puts Memo.fib 1000 # => 70330367711422815821835254877183549770181...
実装はこんな感じ. Ruby の動的で柔軟なインターフェースのおかげで,簡単に実装できる.Ruby すごい.
module Memo @@memo ||= {} def self.method_missing(name, *args, &block) raise ArgumentError unless block_given? && args.empty? @@memo[name] = Hash.new do |h, k| h[k] = block.call(*k) end define_singleton_method(name) do |*a| @@memo[name][a] end unless method_defined? name end end
本当は Memo.define(:fib) do ...
とかして,メソッドを定義していることを明示したほうが良いのかもしれないけれど,method_missing
使ってみたかったのと DSL っぽくしてみたかったので Memo.fib do ...
だけで定義できるようにしてみた.その代わり,定義時(最初に呼び出した時点)でブロックを付けなければ ArgumentError
を出すようにしてある.