2015-02-07 67 views
5

我喜歡如何在Ruby中,你可以通過方法爲塊,像這樣使用Symbol#to_proc與自定義方法符號#to_proc

[1.0, 2.0, 3.0].map(&:to_i) 
#=> [1, 2, 3] 

我也可以定義自己的拉姆達,times_two,並把它作爲一個塊以及:

times_two = ->(x) {x * 2} 

[1, 2, 3].map(&times_two) 
#=> [2, 4, 6] 

雖然我貌似不能times_two作爲符號:

[1, 2, 3].map(&:times_two) 
#=> ArgumentError: wrong number of arguments (0 for 1) 

然而,當我試圖做同樣的方法我得到一個錯誤:

def times_three(x) 
    x * 3 
end 

[1, 2, 3].map(&times_three) 
#=> ArgumentError: wrong number of arguments (0 for 1) 

[1, 2, 3].map(&:times_three) 
#=> ArgumentError: wrong number of arguments (0 for 1) 

我猜我不能這樣做,因爲times_three是一種方法,而不是一個Proc。

那麼如何定義自定義方法,以便在上面的第一個示例中以to_i的方式使用Symbol#to_proc方式?

例如,我該如何做到這一點?

[1, 2, 3].map(&:times_three) 
#=> [3, 6, 9] 

編輯: 我看了視頻下面貼,顯然可以使用method方法去接近符號#to_proc:

def times_three(x) 
    x * 3 
end 

t_three = method(:times_three) 
[1, 2, 3].map(&t_three) 
#=> [3, 6, 9] 

但是,它不是相當符號#to_proc:

[1, 2, 3].map(&:t_three) 
#=> NoMethodError: undefined method `t_three' for 1:FixNum 

回答

5
class Integer 
    def times_three 
    return self * 3 
    end 
end 

,因爲times_three現在是Integer類的方法,你可以做符號來處理...

[1, 2, 3].map(&:times_three) 

如果你想訪問的方法不是對象類的一部分,但作用於對象,你需要將對象作爲參數傳遞給方法...

def times_three(x) 
    x * 3 
end 

[1, 2, 3].map{|i| times_three(i) } 

symbol to proc需要使用該對象作爲接收者。

[1, 2, 3].map(&:some_action) 

相當於

[1, 2, 3].map{|i| i.some_action} 
+0

非常感謝這個清晰的解釋,史蒂夫。現在我知道如何做到這一點,是否可以接受的做法是用這種方法來修補核心類以清理複雜或重複的塊? – garythegoat 2015-02-08 00:07:00

+0

嗯,是的,只要意圖清楚,並有好處,猴子補丁肯定沒問題。 本週我有一個rails應用程序,其中強制性輸入字段在標籤中有星號,例如, 「'名字*''和''城市*'',企業突然想要所有的星號變成紅色的字體顏色。我可以寫一個像red_asterisk('First Name *')這樣的輔助方法,但是更容易的方法是修改String類的First Name * red_asterisk然後在'*'上執行全局查找/替換操作。 ''所以它變成了'*'。red_asterisk' – SteveTurczyn 2015-02-08 00:23:11

+0

史蒂夫,正如你所知道的那樣,'return'是不需要的。然而,「自我」是。我假設'self'必須是明確的,例如'*','%'等方法都是用語法糖調用的。你或其他人知道這是否屬實? – 2015-02-08 04:39:59

1

您必須在IntegerNumeric上定義times_three

符號來解釋PROC通過彼得庫珀:現在https://www.youtube.com/watch?v=aISNtCAZlMg

+3

而不是鏈接到隨機參考,你應該寫簡短的說明/它拷貝到這裏,給鏈接源爲您anwser。 – Smar 2015-02-07 23:24:14

+0

感謝您的視頻。然而,它並沒有說明爲什麼我必須在Integer或Numeric上定義'times_three''。它顯示了Ruby在採用Symbol#to_proc之前如何在類上實現'to_proc'',但該視頻並未顯示如何以這種方式定義自己的方法。 – garythegoat 2015-02-07 23:36:45

+1

@garythegoat:它確實顯示了'Symbol#to_proc'是如何實現的,即它在塊的第一個參數上調用方法,將塊的其他參數作爲方法調用的參數傳遞。在你的情況下,塊的第一個參數是'1'(在第一次迭代中),並且沒有其他參數,所以需要定義'Symbol#to_proc'調用'1.times_three',ergo,'times_three'在'1'的一個類中,即Fixnum,Integer,Numeric,Object,Kernel或BasicObject。不幸的是,[文檔是廢話](http://ruby-doc.org/core-2.2.0/Symbol.html#method-i-to_proc),... – 2015-02-08 01:08:24