這是ActiveSupport擴(kuò)展的一個(gè)方法。原代碼如下:
class Symbol
? def to_proc
??? Proc.new { |*args| args.shift.__send__(self, *args) }
? end
end
它擴(kuò)展出這種用法:
(1..5).map(&:to_s)
map原本是要接受一個(gè)block參數(shù),普通的用法是:
(1..5).map{|e| e.to_s}
或者:
proc = Proc.new{|e| e.to_s}
(1..5).map(&proc)
上面這個(gè)(1..5).map(&:to_s)用法可以拆成3步來(lái)解釋:
sym = :to_s
proc = Proc.new{|*args| args.shift.send(sym, *args)}
(1..5).map(&proc)
有個(gè)疑問(wèn),經(jīng)過(guò)yanping.jia解釋,map(&:to_s)因?yàn)槌霈F(xiàn)了&符號(hào),所以:to_s會(huì)執(zhí)行to_proc方法,然后與&一起合成&proc交給map處理。雖然說(shuō)得通,不過(guò)我總覺(jué)得這個(gè)解釋中,&這個(gè)符號(hào)做了2次工作,是否合理?
這種用法原本是Ruby Extensions Project發(fā)明的,在RoR中作了點(diǎn)修改。原來(lái)的版本是:
class Symbol
??? def to_proc
????? proc { |obj, *args| obj.send(self, *args) }
??? end
end
它使用2個(gè)參數(shù)來(lái)分出一個(gè)參數(shù),而RoR版本則使用shift分出來(lái)。
剛才又想了一下,yanping.jia的解釋應(yīng)該是合理的,解釋器看到&:id時(shí),先會(huì)判斷是否是一個(gè)方法調(diào)用,如果是則需要把:id轉(zhuǎn)成一個(gè)proc。否則就是語(yǔ)法錯(cuò)誤了。