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 來寫。
果然魔鬼都躲在細節裡!
如果寫得有錯再請不吝指正,感謝!