Ruby面試精選30題 - Day22 and 和 or 比較
and
和 &&
以及 or
和 ||
的意思雖然一樣,但就像以前在數學課學過的先乘除後加減
的概念一樣,程式中的運算子之間也具有優先順序之分。符號的&&
, ||
的優先權高於關鍵字and
, or
,請參考Ruby API。
重點摘要:
- Ruby經典面試題目 #22
- short-circuit evaluation 最短路徑計算
- 使用
&&
,||
,不要使用and
,or
- && 與 and : 有初始值的情況下
- && 的優先權高於
=
and
的優先權低於=
- 番外篇:Control-flow modifiers
Ruby經典面試題目 #22
- [and], [or] 和 [&&], [||] 比較?
What is the difference between[and]
,[or]
and[&&]
,[||]
?
基本上而言:
and
就是&&
(且)or
就是||
(或)
short-circuit evaluation 最短路徑計算
事有輕重緩急,資源要放在要緊的地方。要比較哪個運算式先處理之前,在此我們介紹一個概念: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
and
andor
keywords 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的:
…
and
even has lower precedence than=
. 出處
因此,再次強調,使用 &&
, ||
,不要使用 and
, or
。
&& 與 and : 有初始值的情況下
&&
與 and
都是且
的意思。
我的鐵人賽日記IronmanDairy
來到第22天,且第22天是個偶數天,顯示為true.
IronmanDairy = 22
p IronmanDairy == 22 && IronmanDairy % 2 == 0 #=>true
和
IronmanDairy = 22
p IronmanDairy == 22 and IronmanDairy % 2 == 0 #=>true
結果相同。
以上例子,我們明白到 &&
和 and
可以確認一串條件判斷式,其中是否有false
或nil
的部分,全部為true
的情況,才會通過條件判斷。
&& 的優先權高於 =
談到優先權,開車的朋友可以聯想到路權,直行車的權利大於轉彎車。 &&
就像直行車一樣:
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
喔!
番外篇:Control-flow modifiers
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 exercise, or you won't be healthy!
改寫為
You won't be healthy unless you do exercise!
不過,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