iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 9
2

Block

大家應該都還記得,Ruby是一款物件導向程式語言(Objecte-Oriented Programming, OOP),所以在Ruby裡幾乎什麼東西都是物件。但也有少數例外例子,像是Block就不是一個物件,因此Block沒有辦法單獨存在,所以單獨執行會出現錯誤。

{ puts "Hello" }            # SyntaxError
action = { puts "Hello" }   # SyntaxError

Block使用時需要接在方法後面
但是Block本身也不是參數

建立Block

我們會在程式碼看到 do ... end 以及 {} 的寫法就是我們所說的Block
在Ruby會利用Block來傳遞方法,在方法裡的會在兩個 | 之間來定義參數,舉例來說大概長這樣:

do … end 的寫法
通常建議多行程式碼得時候使用do ... end

[1, 2, 3].each do | num |
	puts num
End

大括號 { } 的寫法
則只有單行程式碼時才會使用{},可讓語法看起來精簡

[1, 2, 3].each { | num | puts num }

所以當我們在Block裡看到 |num| 這樣定義的參數是一個區域變數,它只能活在Block範圍裡,一旦離開Block之後就會失效。

Block & yield方法

要讓Block執行內容,可使用yield方法調用block
使用yield暫時把控制權交棒給Block,等Block執行結束後再把控制權交回來。

def hi_yield
  puts "= start ="
  yield                 # 暫時交棒給Block
  puts "= end ="
end

hi_yield { puts "Hello" }

# = start =
# Hello
# = end =

yield方法將轉控制權給Block的時候,也可以順便把值帶給Block。

def hi_yield
  puts "= start ="
  yield 123              # 暫時交棒給Block,並且傳數字123給Block
  puts "= end ="
end

  say_hello { |x|
    puts "hi,這裡是 Block,我拿到 #{x} 囉!"       # |x|會收到來自yield得值123
 }
 
# = start =
# hi,這裡是 Block,我拿到 123 囉!
# = end =

有一種狀況是方法實作裡面有yield,但是呼叫方法的時候卻沒有block,此時執行方法有錯誤訊息”no block given (yield) (LocalJumpError)”。
在這種狀況要讓方法在呼叫的時候也能正常執行,我們可以在yield那邊加入一個條件式判斷 if block_given?

def hi_block
  if block_given?
    yield
  else
    "no block"
  end
end

hi_block                  # => "no block"
hi_block { "hello" }      # => "hello"
hi_block do "hello" end   # => "hello"

參考連結:
為你自己學 Ruby on Rails
談談Ruby中的block


上一篇
Day08 | 模組 include v.s extend
下一篇
Day10 | Proc vs Lambda
系列文
從色彩繽紛到只看亂碼日子,學程式從 Ruby 出發!30

尚未有邦友留言

立即登入留言