表題通り違和感をまとめる。
前提としてメモ化とは
Wikipedia曰く以下の通り
メモ化(英: Memoization)とは、プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン(関数)の呼び出し毎の再計算を防ぐ手法である。 (中略) メモ化された関数は、以前の呼び出しの際の結果をそのときの引数と共に記憶しておき、後で同じ引数で呼び出されたとき、計算せずにその格納されている結果を返す。メモ化可能な関数は参照透過性を備えたものに限られる。すなわち、メモ化されたことで副作用が生じない場合に限られる。 - メモ化 - Wikipedia
ということでメソッドや関数において、同一の引数の場合は再計算せず保存した値を出すことで速度を稼ぐ手法。
Rubyの簡単な例
フィボナッチ数列の例が多いのでそれを題材とする、まずはメモ化しない例
class CalcFibonacci # フィボナッチ数列は1個前と2個前の合計値 def fibonacci(n) # 0と1は前がないので if n <= 1 n else fibonacci(n-1) + fibonacci(n-2) end end end
これを計算結果をmemorizeすると以下
class CalcFibonacci def initialize @cache = {} end def fibonacci_with_memorize(n) # すでに計算済みであれば返却 return @cache[n] if @cache.has_key?(n) if n <= 1 result = n else result = fibonacci_with_memorize(n-1) + fibonacci_with_memorize(n-2) end @cache[n] ||= result result end end
メモ化することで再計算がされなくて済む
メモ化のようでメモ化ではない例
Railsにおいて以下の動作がメモ化の例として取り上げられることがある。
def user @user ||= User.find(params[:id]) end
一見メモ化のように見えるが、メモ化は以下の通りなので趣が違う。
メモ化された関数は、以前の呼び出しの際の結果をそのときの引数と共に記憶しておき、後で同じ引数で呼び出されたとき、計算せずにその格納されている結果を返す。
これはparamsの値を使っている時点でクラスの状態に左右されるため、引数の値を使うという部分でことなる。そのため上記のようなRailsの例はメモ化というよりはDB読み込みのキャッシュとなる。