#代碼來源:http://rubyer.me/blog/917順便學習 Ruby的4種閉包:blocks, Procs, lambdas 和 Methods。
#firstclass Array def iterate! self.each_with_index do |n, i| self[i] = yield(n) yield(n) end endendarray = [1, 2, 3, 4]array.iterate! do |x| x ** 2endputs array.inspect# => [1, 4, 9, 16]#secondclass Array def iterate!(&code) #為iterate!傳遞一個參數&code,&表示這個參數是block。 self.each_with_index do |n,i| self[i] = code.call(n) #在iterate!中沒有使用yield而是call。 end endendarray.iterate! do |n| n ** 2endputs array.inspect#third# ---PROC Procs 過程block與Proc惟一的不同是:block是不能儲存的Proc,一次性的。square = Proc.new do |n| n ** 2endclass Array def iterate!(code) #now these is not &code, not null, but code !! #注意:並沒有在 iterate!的參數頭部添加&,因為Proc只是一個普通類,不需要特殊處理。 self.each_with_index do |n, i| self[i] = code.call(n) end endendarray.iterate! square puts array.inspect
來源:http://rubyer.me/blog/917
首先,我們開啟Array,並添加進iterate!方法。方法名以!結尾表示危險方法,引起注意。現在我們就可能像使用collect!一樣使用iterate!
與屬性不同,在方法中不需要指定block的名字,而是使用yield來調用。yield會執行block中的代碼。同時,注意我們是怎麼把n(each_with_index當前處理的數字)傳給yield的。傳給yield的參數即對應了block中的參數(||中的部分)。現在n就能被block調用並在yield調用中返回n**2。
整個調用如下:
1、一個整數組成的數組調用iterate!
2、當yield被調用時,把n(第一次為1,第二次為2,…)傳給block
3、block對n進行n**2。因為是最後一行,自動作為結果返回。
4、yield得到block的結果,並把值重寫到array裡(這裡用了self,在class和module的定義中,self代表這個class或這module對象,拓展閱讀:http://fuliang.iteye.com/blog/272370)。
5、資料中每個對象執行相同操作。
def callbacks(procs) procs[:starting].call puts "Still going" procs[:finishing].callendcallbacks(:starting => Proc.new { puts "Starting" }, :finishing => Proc.new { puts "Finishing" })# => Starting# => Still going# => Finishing
1、(:starting => Proc.new { puts "Starting" }, :finishing => Proc.new { puts "Finishing" } ) 這裡定義了一個雜湊表或者說字串符號 (Symbol) 。(一個 Symbol 物件皆為冒號開頭,例如 :foo
或 :foo_bar
。它的作用就是代表一個名字,最大的作用就是當做 Hash 的鍵 (key),例如{ :foo => 1, :bar => 2 }
,在這裡我們只需要一個識別的名字,不需要使用字串物件。使用 Symbol 寫法更簡潔和獲得效能上的好處。)
2、:starting => Proc.new { puts "Starting" } 鍵KEY為 :starting,鍵VALUE為 一個Procs 過程。
3、procs[:starting].call 直接調用 儲存在 procs[:starting] 中的 Procs 過程
BTW:什麼時候用blocks而不用Procs呢?我一般這樣判斷:
1、Block:方法把一個對象拆分成很多片段,並且你希望你的使用者可以與這些片段做一些互動。
2、Block:希望自動運行多個語句,如資料庫遷移(database migration)。
3、Proc:希望多次複用一段代碼。
4、Proc:方法有一個或多個回調方法(callbacks)。
未完,明天繼續。