2009-08-26 35 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:我解決了這個問題。這是我的一個使用錯誤。在第一種情況下,我將值重新分配給block參數,而不是修改它。我能夠重寫代碼並獲得預期的結果。

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

更新2:此處使用的代碼僅用於演示此問題。我的實際代碼不像這樣。

+0

我們可以有一個你想要做什麼的真實例子嗎? –

+1

我解決了這個問題。這是我的一個使用錯誤。 在第一種情況下,我將值重新分配給塊參數,而不是修改它。 我能夠重寫代碼並獲得預期的結果。 「abc」.tap {| o | o.replace「xyz」} –

回答

8

對象#tap總是返回執行該塊後傳遞給它的原始對象,即使該塊返回不同的東西。

這裏的好處是,您可以將點擊放入鏈的中間並在不修改原始值的情況下測試對象的值。

這意味着如果您將「abc」傳入tap,它將執行該塊並返回「abc」。由於範圍限定,你的任務並不意味着任何事情。同樣,如果你將一個空數組傳遞給tap,它會返回一個空數組。但是,在第二個示例中,您修改了原始值。修改原始文件的操作,例如< <或gsub!或者同樣會在它返回之前修改對象,因此你會得到一個不同的值。

查看http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions瞭解更多關於如何使用水龍頭的較酷示例。不要將它用於分配或修改,否則你會得到不可靠的結果。

更新:爲了您的編輯,爲什麼這可以解決您的問題?我不明白爲什麼當你只需要調用對象本身的替換函數時,你可以調用tap來做替換。點擊提供給你什麼好處?

+2

是的,使用'tap'做一個簡單的替換是沒有意義的。我的實際代碼不像這樣。 而不是發佈一大塊代碼,我想出了這個例子來重現這個問題。 我傾向於使用「水龍頭」進行調試。最近我已經開始使用'點擊'就地'返回'。 一旦我重新閱讀Tap方法的Rails源代碼,我的錯誤就變得明顯了。 –