Ruby東海32回に参加した
Ruby東海 第32回 勉強会 - Ruby東海 | Doorkeeperに参加した。
@antimon2さんからメモ化の発表があって、ひとりで「わからん」って騒いでたのが私です。
コードを超絶簡略化すると
class MemoSample def hello(name) @greet ||= Hash.new { |hash, name| hash[name] = "hello #{name}" } @greet[name] end end memo = MemoSample.new puts memo.hello("Tom") puts memo.hello("Ken") puts memo.hello("Tom")
ですが、ハッシュにメモを記録する所が全然わからんかった。Ruby力なさすぎて辛い。
つまった所1
memo.hello("Tom") で1回だけ @greet が作成されるので、memo.hello("Ken") では @greet["Ken"] で nil が返ってくるのでは?
こたえ1
Hash.new に渡したブロックが遅延評価されるので、"Ken" に応答できる。
イメージとしては
@greet = { "Tom" => "hello Tom", "Ken" => {後で計算する}, "Marry" => {後で計算する} }
というハッシュが最初に作られて、後で計算する所は @greet["Ken"] が呼ばれてからブロックを実行する。
いったん計算すれば、
@greet = { "Tom" => "hello Tom", "Ken" => "hello Ken", "Marry" => {後で計算する} }
になるから、メモ化 ( ゚Д゚)ウマー てこと。
つまった所2
後で計算するとして、ブロック { |hash, name| hash[name] = "hello #{name}" } は memo.hello("Tom") の呼び出し時に定義している。
結局 @greet[key] にはいつも "hello Tom" が格納されてしまうのでは?
こたえ2
ブロック引数に渡した name と hello の引数は別物 { |hash, key| hash[key] = "hello #{key}" } と同じ。
{後で計算する}箇所は指定されたキー "Ken" によって計算されるだけ。