3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JavaScript: クロージャーでメモ化してくれる関数を作ってみた

Last updated at Posted at 2019-01-08

メモ化っていまいちよくわかっていなかったが、「クロージャを使ってメモ化」を読んで初めてピンときたので、自分でわかるようにES6で書いてみました。

まずは普通に

メモ化してないバージョンのフィボナッチ数列と階乗です。

//フィボナッチ数列
const fibo = n =>
  (n === 0)? 0
  : (n === 1)? 1
  : fibo(n-1) + fibo(n-2)

//階乗
const facto = n =>
  (n === 0)? 1
  : (n === 1)? 1
  : n * facto(n-1)

メモ化した

//フィボナッチ数列
const fibo2 = (
  () =>{
    const memo = [0,1]
    const a = n =>
      (n >= memo.length)? memo[n] = a(n-1) + a(n-2)
      : memo[n]
    return a
  }
)()

//階乗
const facto2 = (
  () =>{
    const memo = [1,1]
    const a = n =>
      (n >= memo.length)? memo[n] = n * a(n-1)
      : memo[n]
    return a
  }
)()

memoには最初初期値のみが入っていて、memo[n]がなかったら再帰的に計算してmemo[n]に代入しつつ返し、memo[n]があればそれを返す、という作戦です。

メモ化してくれる関数

上のふたつを比べると、初期値と再帰的に計算してる部分が違うだけなので、初期値を inits 、計算規則を rule として引数にくくりだしてみます。

const memoizer = inits => rule =>{
  const memo = [...inits]
  const a = n =>
    (n >= memo.length)?  memo[n] = rule(a)(n)
    : memo[n]
  return a
}

これを使うとそれぞれこうなります。

//フィボナッチ数列
const fibo3 = memoizer([0,1])( a => n => a(n-1) + a(n-2) )

//階乗
const facto3 = memoizer([1,1])( a => n => n * a(n-1) )

それぞれ,
$ a_{0}=0,a_{1}=1,a_{n}=a_{n-1}+a_{n-2} $

$ a_{0}=1,a_{1}=1,a_{n}=n a_{n-1} $
に、見えてきません?
こうしておくと、初期値と漸化式で表わされる数列が簡単にメモ化して使える。便利かも。

追記:非再帰版

const memoizer = inits => rule =>{
  const memo = [...inits]
  const a = n => {
    if(n >= memo.length) {
      for(let i = memo.length; i <= n; i++) {
        memo[i] = rule( a )( i )
      }
    }
    return memo[n]  
  }
  return a
}
3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?