掌握Ruby世界就要先懂:區塊
在 Ruby 世界中有著區塊(本篇將稱 block)的特殊語法,跟語言的執行程序上有大大的關聯,今天就來好好跟大家介紹這些部分吧!
區塊 Block
前面有跟大家說到 ruby 幾乎甚麼都是物件,但唯獨 block 這個東西他不能算是物件,而
block 在 ruby 中有兩種:
- {} 之內
- do…end 的範圍內
Block 的特性
總結有以下的特性:
- 一段不會被主動執行的程式碼
- 不是物件
- 像寄生蟲一樣需要依附在某些方法或物件,且不是參數
Block 會不會執行,要看宿主臉色,是否有 yield
可以看下面的例子,我們定義一個吃東西的方法,food 是參數,下面的兩種 block 類型其實都不會被執行,既使看起來有被呼叫到,就像我們上面說的特性,不會被主動執行,也不是參數。
1 | def eat_something(food) |
如何執行? (yield 控制權轉讓)
不知道大家有沒有在馬路上看過這樣的標誌?
大家應該知道這樣的號誌出現就是行車要禮讓行人的路口,等行人過去之後才能繼續前進。
其實 block 的運作就是像是這樣的情境喔!!
當出現 yield 的時候,區塊內的程式碼就會馬上被執行,而這樣的狀況其實是控制權的轉讓,當執行完成後再交出控制權回去依序執行剩下的程式碼。
舉個例子來說:
下面個別字串後面括號的順序就是執行的順序喔! 可以看到 yield 表示將控制權交給 block { } 內的程式碼
1 | def drive_car |
傳遞參數給 Block
Block 不是參數,但可以做為傳遞參數的角色。
轉讓的同時,還可以帶上拌手禮傳遞參數,依照傳遞的多寡可以依序轉讓。
1 | def block_pass_one |
如果沒有 Block 但卻 yield 的話?
會出錯喔!! 控制權轉讓之後沒有 block 可以接的話就會有 localJumpError。
def say_hello # 轉讓控制權,往下找到 test two 的方法
yield
end
say_hello # no block given (yield) (LocalJumpError)
block 回傳值
Block,不用寫 return,最後一行的執行結果會自動變成回傳值。像是一些方法的使用可以看出來,如下面這些例子
1 | # map 與 select 方法 {} 之間的運算就是最後的回傳。 |
如果使用 return 在 block 中呢?
也會出現 localjumperror,因為 Block 不是一個方法,不知道 Return 到哪裡去,所以造成錯誤。
1 | p (1..100).select{ |x| return x % 2 == 0 } |
do…end 及 大括號 {} 之間差異?
一般來說是一樣的,但可能會有優先度的差別,在一些方法的寫法上導致類似先乘除後加減的狀況。
- Block 的內容如果有多行,會建議使用 do .. end 寫法
- 如果只有一行,則建議使用大括號寫法
1 | p [*1..10].map { |i| i * 2 } |
以上就是基本對於 block 相關的介紹,後面可以開始進入 ruby 這充滿物件的世界中-物件導向,了解一下關於物件導向的一些概念吧。
參考資料: