2011-01-27 16 views
22

最近、私はtapを使用して、新しい変数に値を "ドリリング"することができることを発見しました。例えば、作成し、このようなアレイを充填する:Ruby 'tap'メソッド - 内部割り当て

array = [].tap { |ary| ary << 5 if something } 

truthyあるarraysomething場合に5をプッシュするこのコードとそうでない場合、arrayは空のままです。

しかし、私はこのコードを実行した後に理由を理解していない:

array = [].tap { |ary| ary += [5] if something } 

arrayは空のまま。誰でも助けてくれますか?

答えて

38

最初のケースでは、arrayaryは同じオブジェクトを指します。その後、<<メソッドを使用してそのオブジェクトを変更します。 arrayaryが指すオブジェクトが変更されました。

arrayaryは、両方とも同じ配列を指しています。今すぐary変数を再割り当てすると、aryは新しい配列を指すようになります。ただし、aryの再割り当てはarrayには影響しません。ルビの再割り当てでは、再割り当ての前に同じオブジェクトを指していても、変数は他の変数に影響することはありません。言い換えれば

arrayはまだx次の例では42ではないだろうというのと同じ理由のために空である:

x = 23 
y = x 
y = 42 # Changes y, but not x 

編集:インプレース別の配列を追加するには、あなたがconcatを使用することができますこの方法も+=を使用するよりも速くなければなりません。

+5

ADD: 'a + = b'は' a = a + b'のように動作します - ここでは新しいオブジェクトを作成する事がより明らかです。 – Nakilon

+1

@Nakilon:OPが明示的に割り当てについて話していたことを考えると、その部分が彼にはっきりとしていると仮定しました。 – sepp2k

+0

私は理解したと思います。それは割り当て操作のbeacuseを動作しません。 array = [].tap { |ary| [5].each{ |v| ary << 5 } } ---あなたのコメントに書式を追加するにはどうすればいいですか? – mdesantis

20

私は、このビットに拡張したい:

  1. []からarray、空の配列に割り当てます。

    array = [].tap { |ary| ary << 5 if something } 
    

    が、これは何(somethingと仮定すると、っぽい本当です)。

    array.object_id = 2152428060 
    
  2. aryとしてブロックに[]を渡します。 aryおよびarrayは、同じ配列オブジェクトを指しています。

    array.object_id = 2152428060 
    ary.object_id = 2152428060 
    
  3. ary << 5 < <それは受信側オブジェクトを修正する意味、推移的方法です。これは.map.map!のようにメソッドの呼び出しに "012 in this place!"を意味するメソッド呼び出しに!を追加するという慣用法に似ています(ただし、メソッド名には内在的な意味はありません)。ary 5が挿入、そうしているary = array = [5]

    array.object_id = 2152428060 
    ary.object_id = 2152428060 
    

我々はarrayは、第2の例で[5]

に等しいで終わる:

array = [].tap{ |ary| ary += [5] if something }  
  1. 同じ
  2. 同じ
  3. ary += 5+=ary = ary + 5の略であるので、そのために、第一の変形例(+)、次いで割り当て(=)です。それは、オブジェクトを適所に変更する外観を与えますが、実際には変更しません。全く新しいオブジェクトを作成します。

    array.object_id = 2152428060 
    ary.object_id = 2152322420 
    

そこで元のオブジェクト、object_id=2152428060、及びaryと空の配列、object_id = 2152322420で5を含む一つの項目を持つ配列としてarrayで終わります。この後はaryに何も起こりません。すでに起こっている元の割り当てarrayとは関係ありません。 Tapはarrayが割り当てられた後ブロックを実行します。

+1

これは最も優れた答えと解説です。 – tamouse

+1

大きな説明 - よくできました。 – Jurgen

関連する問題