3

ruby メタプログラミングを試していますが、instance_eval() で混乱が生じました。

以下の例を参照してください

@instance_var = 'instance_var'
local_var = 'local_var'
obj = Object.new
obj.instance_eval { p @instance_var; p local_var }
obj.instance_eval { @instance_var  = 'instance_var_in_obj'; local_var = 'local_var_in_obj' }
p @instance_var; p local_var

@instance_var と local_var の両方がブロックでパス/変更できると予想していますが、取得しました

nil
"local_var"
"instance_var"
"local_var_in_obj"

その結果、ローカル変数を共有 (パス/変更) できますinstance_valが、インスタンス変数はself共有できません。

と約instance_exec

obj.instance_exec(@instance_var) {|instance_var| p instance_var; instance_var = @instance_var }
=> "instance_var"
@instance_var
=> "instance_var"

今、私は自分の外側のインスタンス var を渡すことができますが、それを変更することはできません。

@instance_arr = []
obj.instance_exec(@instance_arr) {|instance_arr| instance_arr << 'in_block' }
@instance_arr
=> ["in_block"]
obj.instance_exec(@instance_arr) {|instance_arr| instance_arr = [] }
@instance_arr
=> ["in_block"]

配列のインスタンス var を使用すると、インスタンス var を変更できますが、現在の配列オブジェクト内でのみ変更できます

要約プレイでinstance_eval、またはinstance_execインスタンス変数ではなくローカル変数を使用しますか?

私が見逃したいくつかの概念はありますか?

4

2 に答える 2

1

友人からのいくつかの検索とアドバイスの後、私は問題を理解したと思います. ruby では、コードを実行するときに と の 2 つがありますContextselfsetを使用する場合と使用しない場合は、最初にオブジェクト内にあるかどうかがチェックされます。そうでない場合、Ruby はそれがメソッドであると判断し、オブジェクトを検索してその定義を見つけて呼び出します。 . これを考えてください:bindinglocal varsmethodself.xxxbindinglocal varself

class A
  def test
    4
  end
  def use_variable
    test = 5
    test
  end
  def use_method
    test = 5
    self.test
  end
end
a = A.new
a.use_variable # returns 5
a.use_method   # returns 4

これWHYinstance_eval、そのドキュメントが指定されたブロックでinstance_eval変更されたばかりで触れていないと説明されているため、メソッドは同じオブジェクト内にある new 、ローカル valsで検索されます。selfbindingselfbinding

これについてinstance_execはよくわかりませんが、インスタンス vars (接頭辞 vars 付き) のように思われますが、直接スキップして検索されるためselfbinding古いブロックに属しているブロックから、新しいブロックの新しいブロックとして取得しました。(ブロックには独自のスコープがあります)しかし、その値は実際には新しいメソッドの参照であるため、同じものを共有しているため両方を変更しますが、新しいものを新しいものに割り当てると、同じものを参照しなくなりますそれは 2 番目です。instance_exec@instance_arrselfinstance_execlocal varbinding@instance_arrlocal varpushArray instanceArray instancelocal varArray instanceWHY

于 2015-04-19T08:01:20.043 に答える