2014-01-30 44 views
3

我發現,實現自定義符號#to_proc在Ruby中此示例代碼:爲什麼Symbol#to_proc具有這種類型的行爲?

class Symbol 
    def to_proc 
    puts "In the new Symbol#to_proc!" 
    Proc.new { |obj| obj.send(self) } 
    end 
end 

它包括額外的「放......」字符串,以確保它沒有內置的方法。當我執行的代碼

p %w{ david black }.map(&:capitalize) 

結果是:

In the new Symbol#to_proc! 
["David", "Black"] 

但它爲什麼不這樣呢?

In the new Symbol#to_proc! 
["David"] 
In the new Symbol#to_proc! 
["Black"] 

我的邏輯是這樣的:map將元素一個接一個阻塞。塊取第一個元素並執行.to_proc,而不是第二個。但爲什麼只執行一次?

+0

@bjhaid:這不是該答案的重複。完全一樣。 –

+1

@bjhaid:恩,是的,我要繼續前進,不同意你在這裏。 –

+0

http://stackoverflow.com/questions/1961030/ruby-ampersand-colon-shortcut – andHapp

回答

3

在Ruby中,地圖可與一個塊。 &運營商在它後面的對象上調用to_proc,並將從調用to_proc返回的值傳遞給映射爲block。有了這些信息,我們再來看看你的例子。在你的例子中,&:capitalize將致電方法:capitalize。因爲,:capitalize是一個Symbol,它將在Symbol類上調用to_proc,由您重新定義。

:capitalize.to_proc 

將返回:

In the new Symbol#to_proc! 
=> #<Proc:[email protected](irb):4> 

&操作者將使用返回的PROC對象,並傳遞進程內對象映射爲一個塊。在您重新定義的to_proc方法定義中,puts剛剛得到執行,並且從puts打印到控制檯(假設您正在控制檯中運行此操作),您將看到它打印出來。它永遠不會傳遞給地圖,所以你永遠不會看到它打印兩次。

但是,如果您想要預期的行爲,請使用第一個答案。希望能幫助到你。

+0

這是一個完美的答案,現在我明白髮生了什麼。謝謝! – rubybaseddev

6

to_proc方法被調用一次以返回一個Proc對象,然後重複使用該對象,以便您看到正確的行爲。

如果移動內賣出期權,你會看到你期待什麼:

class Symbol 
    def to_proc 
    Proc.new { |obj| 
     puts "In the new Symbol#to_proc!" 
     obj.send(self) 
    } 
    end 
end 
+0

謝謝你的解釋,但我不明白爲什麼Proc對象只創建一次。爲什麼每個地圖塊調用都沒有新的Proc對象?我確信Ruby正確執行代碼,但我無法找到這種情況的很好解釋。 – rubybaseddev

+1

爲什麼你會想要一個全新的proc每個循環?這是非常浪費的,因爲'map'和類似函數的全部概念都是對許多對象應用完全相同的功能。如果你想對每個元素應用不同的函數,那麼你應該使用'each'並在其中定製一段代碼。這給你最大的靈活性。 – tadman

相關問題