Do..End v.s Braces

話說在 Ruby 裡,Block 可以用 do..end 的方式來寫,也可以用大括號來寫,例如用 do..end 的方式寫:

(1..5).each do |i|
  puts i   # 得到1 2 3 4 5
end

用大括號的方式寫的話:

(1..5).each { |i|
  puts i   # 一樣也是得到1 2 3 4 5
}

不過這兩天在看 The Ruby Way 的時候,看到一段是這樣寫的:

“Note that do and end may be substituted for the braces that delimit a block. There are differences, but they are fairly subtle.”
-- The Ruby Way(2nd edition), Page.22

書裡沒看到特別講到底哪邊不一樣,所以好奇的到處翻了網路上的一些資料,發現原來這兩種寫法的優先順序有一些些的不一樣,來看一段範例:

my_array = [1, 2, 3, 4, 5]

p my_array.map { |item|
  item * 2  # 得到[2, 4, 6, 8, 10]
}

p my_array.map do |item|
  item * 2  # 得到[1, 2, 3, 4, 5]
end

為什麼結果跟預期的不一樣? 原來,因為省略了一些小括號,第二段的程式碼本來的意思是:

p(my_array.map do |item| item * 2 end)  # 得到[2, 4, 6, 8, 10]

但卻因為 do..end 的優先順序比較小,原式被解析成:

p(my_array.map) do |item| item * 2 end # 得到[1, 2, 3, 4, 5]

結果後面的 do..end 還沒開始跑,my_array.map 就先被 p 給印出來了..而用大括號的寫法的優先順序比較高,則不會有這個困擾。這樣那到底什麼時候要用 do..end? 什麼時候要用大括號? 還是乾脆全部都用大括號就好?

基本上如果 Block 的執行結果是會有回傳值的,那就建議用大括號來寫,其它的大致上都可以用 do..end 來寫。

果然魔鬼都躲在細節裡!

如果寫得有錯再請不吝指正,感謝!

工商服務

實體課程:Ruby on Rails 實戰課程
線上課程:五倍學院線上課程