せかいや

いまいるここを、おもしろく http://sekai-in-the-box.appspot.com/

【Ruby】Rubyベストプラクティス 学習の感想

■topic summary
study about Hash.new{}, memoization, "module A; extend self", etc.

 

Rubyベストプラクティス -プロフェッショナルによるコードとテクニック

Rubyベストプラクティス -プロフェッショナルによるコードとテクニック

 
5章が終わったぞー。
以下、気づいたことのメモ。

 

Hashのブロック

おさらい。

hash = Hash.new{|h, k|p "here"; h[k] = [] }
hash["a"] << "aaa"
hash["a"] << "bbb"
p hash

■実行結果

"here"
{"a"=>["aaa", "bbb"]}

Hashのブロックはキーが存在しない時だけ実行される。

 

キーをぐるぐる回す

hash = Hash.new{|h, k|p "here"; h[k] = 0 }
[:a, :a, :b, :a].map{|x| hash[x] += 1 }
p hash  #<= {:a=>3, :b=>1}

 
 

インスタンス変数に(メモ化)

@hash ||= Hash.new{|h, k| h[k]=k.map{|e| e*10}.join}
@hash[key]

 
 

メモ化したい関数に印をつける

 
嵌ったところ

alias の引数はメソッド 呼び出し等の一切の評価は行われません。メソッドの定義内で別名を付けるにはModuleクラスのメソッド Module#alias_method を利用して下さい。

http://docs.ruby-lang.org/ja/2.0.0/doc/spec=2fdef.html#alias

以下では、alias_methodを使っているところに注目。
 

class Test
  def self.fibo(int)
    return int if int==1 || int==0
    fibo(int-1) + fibo(int-2)
  end
  def self.memorize(fnc)
    cache = Hash.new
    original = "__unmemoized_#{fnc}__"
    singleton = class << self;self;end
    singleton.class_eval do
      alias_method original, fnc
      define_method(fnc){|*args|cache[args] ||= send(original, *args)}
    end
  end
  memorize :fibo
end
p Test.fibo(3)

 

 

module A; extend self の意味。

 
たとえばこんなコード。

module Hoge
  def foo1; p "foo1"; end
end
class Huga
  extend Hoge
  foo1  #<= "foo1"
end

extend することで
 ⇒Class内でextend先のメソッドがプライベート呼出し可能

だから、
自分をextendすることで、
 ⇒自分内で自分のメソッドがプライベート呼出し可能
なるほど。
 

module Hoge
  extend self
  def foo1
    p "foo1"
  end
  foo1  #<= extend selfによって 自分のメソッドが呼べる
end

 
ふむふむ。

 

included と inherited の違い。

include はプライベートメソッド

module A
  def self.included(clazz)
    p clazz
  end
end
class B
  include A  #<= "B"が表示
end

includeした時点でフックメソッドが呼ばれる。
  

inherited はインスタンス生成時点

class A
  def self.inherited(base)
    p base
  end
end
class B < A
end
B.new  #<= "B"

 
「<」キーワードはメソッドでないため、
定義時ではなく、インスタンス生成時に呼ばれる。


長い。。