iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 22
1
Modern Web

30天修煉Ruby面試精選30題系列 第 22

Day22 - Ruby比一比: and, or 和 &&, || 比較

  • 分享至 

  • xImage
  •  

Ruby經典面試題目 #22

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 最短路徑計算

事有輕重緩急,資源要放在要緊的地方。要比較哪個運算式先處理之前,在此我們介紹一個概念: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 and or 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天為偶數,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 可確認一串條件判斷式之中是否有falsenil的部分,全部為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 && IronmanDairyNilClass,然而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,請不要用andor喔!

番外篇: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!

andif,這樣是不是比較類似英文語法的邏輯呢?:)

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


上一篇
Day21 - Ruby的布林值: true,false和nil
下一篇
Day23 - Ruby比一比: '==', '===', 'eql?,' 'equal?'
系列文
30天修煉Ruby面試精選30題31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言