0

したがって、私が正しく理解している場合、Object#tap は yield を使用して、プロセスまたはメソッドの実行中に操作する一時オブジェクトを生成します。私がyieldについて知っていると思うことから、yieldは(物)を取り、それが使用されているメソッドに添付されたブロックに(物).dupを与えるようなことをしますか?しかし、私がこれを行うとき:

class Klass
attr_accessor :hash
  def initialize
   @hash={'key' => 'value'}
  end
end

instance=Klass.new
instance.instance_variable_get('@hash')[key] # => 'value', as it should

instance.instance_variable_get('@hash').tap {|pipe| pipe['key']=newvalue}

instance.instance_variable_get('@hash')[key] # => new value... wut?

私は、yield -> new_obj という印象を受けました。これがどれほど正しいかはわかりませんが、ruby-doc で調べてみましたが、Enumerator::yielder が空で、yield(proc) がなく、ファイバー バージョンがありません。実際、Rubyはそれらを使用するために「ファイバー」を明示的に含める必要はありませんか?

したがって、インスタンス変数の読み取りメソッドと temp の書き込みは、代わりにインスタンス変数の読み取り/書き込みになるはずです...これはクールです。ハッシュをインスタンス変数として処理する方法 (変数の名前付き配列の使用に慣れているテーブルよりも大きい場合) を作成しましたが、今は少し混乱しており、その説明が見つかりません。それを可能にしているメカニズム。

4

2 に答える 2

2

Object#tapこれ以上簡単なことはありません:

VALUE
rb_obj_tap(VALUE obj)
{
    rb_yield(obj);
    return obj;
}

ドキュメントから)。それは単に譲歩してから受信者を返します。IRB で簡単に確認するとyield、新しいオブジェクトではなく、オブジェクト自体が生成されることがわかります。

def foo
  x = {}
  yield x
  x
end

foo { |y| y['key'] = :new_value }
# => {"key" => :new_value }

したがって、期待どおり、 の動作はtapと一致します。yield

于 2012-10-25T02:46:07.507 に答える
0

tap受信者を複製しません。ブロック変数には、受信者自体が割り当てられます。その後、tapレシーバーを返します。そのためtap{|pipe| pipe['key']=newvalue}、 のレシーバーtapが変更されます。私の理解では、

x.tap{|x| foo(x)}

次と同等です。

foo(x); x

y.tap{|y| y.bar}

次と同等です。

y.bar; y
于 2012-10-25T02:29:10.303 に答える