evalことはじめ
eval
osamu = 'tezuka osamu' # => "tezuka osamu" eval('osamu') # => "tezuka osamu" # Bindingインスタンスを渡すことでコンテクストを指定できる def context_literature osamu = 'dazai osamu' binding end eval('osamu', context_literature) # => "dazai osamu"
instance_eval
文字列やブロックを渡すと、それを「レシーバの特異クラス定義の中に近いコンテクスト」で評価してくれる。
# 準備 class Novelist attr_reader :works def initialize(*works) @works = works end end dazai = Novelist.new("ningen sikkaku", "syayo") akutagawa = Novelist.new("rashomon", "hana") # usage1: 文字列を渡す dazai.instance_eval('def representative_work; @works[0]; end') dazai.singleton_methods # => [:representative_work] dazai.representative_work # => "ningen sikkaku" # usage2: ブロックを渡す akutagawa.instance_eval {def representative_work; @works[0]; end} akutagawa.singleton_methods # => [:representative_work] akutagawa.representative_work # => "rashomon"
instance_exec
概ねinstance_evalと同じだが、以下の点で異なる。
instance_execだとできないこと
文字列を渡せない
dazai.instance_exec('@works << "otogi zoushi"') # LocalJumpError: no block given
instance_execでのみできること
引数をブロック引数として渡せる
# usage1: 引数なしのブロック(これはinstance_evalでもできる) dazai.instance_exec{@works << 'otogi zoushi'} dazai.works # => ["ningen sikkaku", "syayo", "otogi zoushi"] # usage2: 引数ありのブロック(これはinstance_evalではできない) dazai.instance_exec('good bye'){ |work| @works << work } dazai.works # => ["ningen sikkaku", "syayo", "otogi zoushi", "good bye"]
こういうときにつかえるな!とはまだ想像できないが、instance_execの方が柔軟性が高そうだな?
とりあえずここまで。