iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 9
0
Modern Web

關於 Ruby on Rails,我想說的是系列 第 12

#[Day 12] Ruby 算符優先序 Operator Precedence

  • 分享至 

  • xImage
  •  

一段邏輯複雜的程式碼,可能包含了很多的算符(operator),這些算符孰先孰後是有個先後順序的,就像小學四則運算人人會背的口訣先乘除,後加減 如果不了解,容易有意想不到的 bug 產生。

考考大家

下面的 today 是幾號?

today = '25號' || '26號' && '27號'
today # =>  ?

答案是 "25號"
還不懂優先級的我,會認為是"27號"

原本我是這麼想:
1.首先"25號"先跟"26號"||運算子來判斷,因為第一個"25號"就是true,所以回傳"25號"
2.然後"25號""27號"&&運算子來判斷,兩個都是true所以回傳第二個"27號"
(以上是錯的)

(以下才是對的)
因為&&的優先序比||
所以是先判斷'26號' && '27號',回傳"27號"
再判斷'25號' || '27號',就回傳'25號'

Ruby這麼多算符,誰先誰後?

下面這個表都整理好了,越上面,優先級越高

算符優先序列表 Operator Precedence Table

看完上圖可以觀察到一個邏輯

四則運算 > 比大小 > 是否相等 > 邏輯且/或 > 三元 > 賦值

用 && 跟 || 取代 and 跟 or

在我們公司的legency code(譯:活化石code),還看到前人會使用andor,但是新code就完全沒人用了,而且裝上Rubocop後,還出現警告。
看過前面那張表後,就不難理解為什麼 Rubocop 會建議:

  • &&取代and
  • ||取代or

因為 &&and 雖然中文意思都是,但是兩個的優先序不相等,造成andor可能有意想不到的bug

舉例說明,定義方法second_present?來判斷是否有第二本漫畫,有的話就回傳第二本的書名。然後在方法裡面用@result接住結果,我預期@resultsecond_present?回傳的結果是一樣的

def second_present?(comic1 = nil, comic2 = nil)
 @result = comic1 and comic2
end

second_present?('海賊王', '租借女友' ) # => "租借女友" 
@result # => "海賊王" 

second_present?('海賊王') # => nil 
@result # => "海賊王" 

沒想到@result出乎我意料之外,@result不只沒有回傳第二本書名,而且不管有沒有第二本,都只回傳第一本的書名。
這就是and的雷,因為and的優先序在=後面。

上面這段code如果把and改用&&就能呈現我所希望的結果。
自己操作一次就知道了


上一篇
[Day 11] MVC 架構
下一篇
[Day 13] Model 生成與資料庫遷移
系列文
關於 Ruby on Rails,我想說的是23
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言