2009-08-26 13 views
11

'String'型のオブジェクトに対して 'tap'メソッドを使用しているときに興味深い問題に遭遇しました。Stringオブジェクトの 'tap'メソッドが期待した結果を返さない

"abc".tap { |o| o = "xyz" } # this line returns "abc" instead of "xyz" 

「tap」メソッドは、他のタイプのオブジェクトでも機能します。

[].tap { |o| o << "xyz" } # this line returns ["xyz"] as expected 

Windows XPでRails 2.3.2とRuby 1.8.6を使用しています。

私はここで何が欠けていますか?

更新1:この問題は解決しました。それは私の使い方の誤りでした。最初のシナリオでは、ブロックパラメータを変更するのではなく、ブロックパラメータに値を再割り当てしていました。私はコードを書き直し、期待される結果を得ることができました。

"abc".tap { |o| o.replace "xyz" } 

更新2:ここで使用されているコードは、問題を示すためのものです。私の実際のコードはこのようには見えません。

+0

あなたがしようとしていることの本当の例がありますか? –

+1

この問題は解決しました。それは私の使い方の誤りでした。 最初のシナリオでは、ブロックパラメータを変更するのではなく、ブロックパラメータに値を再割り当てしていました。 私はコードを書き換えて、期待される結果を得ることができました。 "abc" .tap {| o | o.replace "xyz"} –

答えて

8

Object#tapは、ブロックが何か異なるものを返す場合でも、ブロックの実行後に渡された元のオブジェクトを常に返します。

ここでの利点は、チェーンの中央にタップを入れて、元の値を変更せずにオブジェクトの値をテストできることです。

これは、「abc」をタップに渡すと、ブロックを実行して「abc」を返します。 oへのあなたの割り当ては、スコープのために何も意味しません。同様に、空の配列をタップに渡すと空の配列が返されます。ただし、2番目の例では、元の値を変更しました。 < <またはgsub!などのオリジナルを変更する操作同様に、返される前にオブジェクトを変更するので、異なる値を返すことになります。

タップの使い方の詳細については、http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressionsをご覧ください。割り当てや変更にそれを使用しないでください。そうしないと、厄介な結果が返ってくるでしょう。

更新:あなたの編集には、なぜ問題が解決されますか?私はあなたがなぜオブジェクト自体の代わりにreplaceを呼び出すことができるときに置き換えを行うためにタップを呼び出すのか理解できません。あなたを提供することは何のメリットですか?

+2

はい、単純な置換を行うには 'タップ'を使用するのは意味がありません。私の実際のコードはこのようには見えません。 大きなコードを掲示する代わりに、問題を再現するためにこの例を考えました。 デバッグに「タップ」を使用する傾向があります。最近私は、「戻る」の代わりに「タップ」を使用し始めました。 Railsのソースコードをtapメソッドで再読み込みすると、私のエラーが明らかになりました。 –

関連する問題