Day22 [and], [or] 和 [&&], [||] 比較? What is the difference between [and], [or] and [&&], [||] ?`
基本上而言:
and 就是 &&(且)or 就是|| (或)and 和 && 以及 or 和 || 的意思雖然一樣,但就像以前在數學課學過的先乘除後加減的概念一樣,程式中的運算子之間也具有優先順序之分。符號的&&, || 的優先權高於關鍵字and, or(https://ruby-doc.com/core/doc/keywords_rdoc.html)。
事有輕重緩急,資源要放在要緊的地方。要比較哪個運算式先處理之前,在此我們介紹一個概念:short-circuit evaluation(又稱:短路計算、捷徑計算、最小化計算)。
當表達式的結果已經確定時,程式會節省資源,減少不必要的運算。不管是&&.||還是and.or,都會符合最短路徑計算原則。
舉個例子來說:
a = 0
b = 1
if (a == 1 && b%2 == 1)
  p "true"  
else
  p "false"
end # => false
在以上的例子裡,&&代表括弧內的條件判斷必須全部為真才成立。一開始我們指定a = 0,因此,在if (a==1)這個敘述為false的情況,我們不需要走完下一條判斷式b%2 == 1 (b為奇數),這就是「最短路徑計算」。
&&, || ,不要使用 and, or根據RuboCop Headquarters的Ruby Style Guide:
The
andandorkeywords are banned. The minimal added readability is just not worth the high probability of introducing subtle bugs. For boolean expressions, always use&&and||instead.
由於優先權(precedence)的問題,and and or是很容易出bug的:
...
andeven has lower precedence than=. 出處
因此,再次強調,使用 &&, || ,不要使用 and, or。
&& 與 and 都是且的意思。
我的鐵人賽日記IronmanDairy 來到第22天了!!!由於第22天為偶數,IronmanDairy % 2 == 1(除以2的餘數為1)顯示為false.
IronmanDairy = 22
p IronmanDairy % 2 == 1 && IronmanDairy == 22  #=>false
和
IronmanDairy = 22
p IronmanDairy % 2 == 1 && IronmanDairy == 22 #=>false
結果相同。
&&和 and 可確認一串條件判斷式之中是否有false或nil的部分,全部為true的情況,才會通過條件判斷。&&和 and都會遵循「最短路徑計算」。
=談到優先權,開車的朋友可以聯想到路權,直行車的權利大於轉彎車。 && 就像直行車一樣:
p IronmanDairy = 22 && IronmanDairy % 2 == 0
#undefined method `%' for nil:NilClass (NoMethodError)
上列程式竟然出現NoMethodError!!原因是&&有較高的優先權。
對Ruby來說,優先順序變成:
p IronmanDairy = (22 && IronmanDairy) % 2 == 0
由於IronmanDairy尚未初始化(uninitialized),而讓22 && IronmanDairy 為NilClass,然而NilClass 除以2是無意義的。
如果我們把同一條件判斷式,加上適當的括弧隔開:
p (IronmanDairy = 22) && (IronmanDairy % 2 == 0)
#=> true
就可以完成我們要達到的語義目的:
給定鐵人賽日記IronmanDairy這個值為22,且22是個偶數,顯示為true.
and 的優先權低於 =而在上述案例,若 && 改成 and 的意思,就天差地遠了:
p IronmanDairy = 22 and IronmanDairy % 2 == 0 #=> 22
p (IronmanDairy = 22) and (IronmanDairy % 2 == 0) #=> 22
不管括弧是否存在,結果已經變成印出了IronmanDairy指定的數值22,而不是出現我們想判斷的布林值true,因為
IronmanDairy = 22的 = 等號竟然比 and 的優先權還高!!
為了防止誤會大了,難以偵錯出產生的bug,請不要用and或or喔!
and 關鍵字與if有的時候,我們點擊動態網站中的連結,會跳出(showup)意想不到的視窗(suprise):
suprise = suprise.showup and next
寫法等同於if(如果跳出視窗,就進行下一步next):
next if suprise = suprise.showup
如同把 I am hungry and I eat an apple
改寫為
I wanna eat an apple if I am hungry!
把and改if,這樣是不是比較類似英文語法的邏輯呢?:)
or 關鍵字與unless而有的時候,我們點擊連結想連到某個頁面,會出現錯誤訊息404:找不到此網頁:
read_article()? or raise "Could not find this article!"
我們可以寫成:
raise "Could not find this article!" unless read_article()?
如同把 Do more exercise, or you won't be healthy!
改寫為
You won't be healthy unless you do more exercise!
最後,透過今天的Ruby面試題練習,我發現了Ruby Style Guide,如何寫出可讀性佳、好維護的Ruby Code,是需要經過設計的。像Airbnb的Ruby Style Guide有提到,只有在簡單可寫成一行程式碼的情況再使用if/unless,不然也是會錯誤連連喔!
Modifier if/unless usage is okay when the body is simple, the condition is simple, and the whole thing fits on one line. Otherwise, avoid modifier if/unless. link