學幾招 Ruby 運算子 - tricky operators


Posted by Nacho on 2020-09-11

Part1. 學幾招 Ruby 運算子 - 覆寫內建方法

TL;DR

  • 熟悉一些運算子,能少寫一些code、讓codebase變乾淨、codereview 看起來很舒服
  • 了解運算子的特性,也能幫助提升效能、catch例外狀況

Tricky operators

除了前一章,常用的像是+, -, >, <= 這些外,還有一些比較特殊的operator,有一些在其他的程式語言中也有相似的用法,另有些比較像 Ruby 獨有的表達方式。我認為這些特殊tricky的operators,一旦學會,且懂得運用他們,便能享受到許多助於開發的效益,例如讓方法看起來更簡潔、更快理解別人的code、用operator讓你少做點事等。因此,以下整理六個tricky operators:

?: Ternary Operator

很多程式語言都有保留 Ternary operator,因為它就等同if else end,但濃縮成一行,節省空間,也讓codebase看起來更簡潔一些!

"".size == 0 ? "Empty string" : "Non-empty string"
# 如果條件判斷 true,做 ? 後面的事,不然就做 : 後面的事

&. Safe Navigator Operator

&.(Safe Navigator Operator)是個蠻貼心的防呆設計,它會幫你判斷如果物件是nil的情況下,就略過後面的執行方法,例如下面 user 的條件判斷,如果 user 是 nil,則略過執行user.active。

if user && user.active
  # ...
end
# use safe navigator operator
if user&.active 
  # ...
end

||= Or-equals Operator

a||=b(a or-equals b),它完整的意思是:若 a 為 nil 或 false,則 a 等於 b;反之,a 的值維持不變。想像若 a 是一個暫存 api 回傳的變數,當在首次呼叫 api 得到資料後便暫存在變數記憶體內,並重複使用,在Ruby這有個技巧叫“memoization”。

a ||= 100
# 若 a 為 nil 或 false,則將 100 指定給它,反之,回傳 a 自己
# 它實際要表達的是
(defined?(a) && a) ? a : a = 100

<< Shovel/Push Operator

這個 << (Shovel/Push)用到時機,稍特殊一點就是看前面的對象是誰,才會決定運算子本身的行為,例如前面是陣列,就 push 元素到陣列尾端;字串就插入到字串尾端;數字就移動位元(left shift),數字不常用略過。

fruit = []
fruit << "apple"
fruit << "melon" # ["apple", "melon"]
str = ""
puts str << "cat"
puts str << "dog" # "catdog"

!! double-bang Operator

!!a(double-bang a),將 a 轉換成一個布林值並回傳(或說否定自己兩遍,再傳回結果)。另外!a(bang a)也是回傳一個布林值(否定自己一遍)。

!!123 # true->false->true, return true
!!nil # false->true->false, return false
!"nacho" # true->false, return false
!!"nacho" # true->false->true, return true
!"" # 空字串是 true,但被否定後變 false, return false
!!"" # true->false->true, return true

補充:回顧 true/false/nil 超詳細整理

* Splat Operator

* (Splat operator),這個運算子特別之處在於需要依據後方的值,來判斷它是分割一個陣列的元素,還是創造一個新的陣列。以下簡單介紹四招從Tricky operators in Ruby 整理的用法。

# 第一招:將陣列分割
a, b, c = *[1,2,3] # => a= 1, b= 2, c= 3
a, *b = *[1,2,3] # => a= 1, b= [2,3]

# 第二招:產生一個新陣列
*a = 1,2,3 # => a = [1,2,3]

# 第三招:作為函式的參數
coffee_attributes = [:name, :orgin, :desc]
attr_reader *attributes # => the same as attr_reader :name, :origin, :desc

def stuff *args # <= 不需要有明確的參數的順序
   args.join('|')
end

p stuff("Paul", "Tom", "Winssen") # => "Paul|Tom|Winssen"

# 第四招:將hash分割並轉成陣列
h = { :a => "test1", :b => "test2"}
a, b = *h # => a = [:a, "test1"], b = [:b, "test2"]

更多splat operator 在開發上的應用實例分享:
https://medium.com/@eggyy1224/ruby%E7%9A%84splat-operator-f2fa4f7956c7

心得

隨著看別人寫的code的次數增加,漸漸會感覺到operator是種開發者間快速且輕巧的溝通文化!

參考

https://www.rubyguides.com/2018/07/ruby-operators/#Assignment_Operators


#ruby operator #tricky operators







Related Posts

[ JavaScript 06 ] function 傳參數的運作機制

[ JavaScript 06 ] function 傳參數的運作機制

計畫列表

計畫列表

在 AWS 上使用 Docker 安裝 Jitsi

在 AWS 上使用 Docker 安裝 Jitsi


Comments