[Day30] 還在等什麼!快來成為 Ruby 工程師啊!(誤)
終於來到鐵人賽的最後一天了!以為我要寫個完賽心得帶過嗎?雖然很想這樣做,不過,這裡並不是停下腳步的地方啊!
這篇要介紹的是 Enumerator
!
剛開始看到這個詞只覺得陌生 + 困惑
上網查了許久,Enumerator
似乎沒有一個很精準的中文翻譯,但可以找到像是 external
, iterator
, Enumerable Module
這些關鍵字。
但其實它一直都在我們身邊。
平時 coding 可能就已經看過它,那就是當使用 each
方法操作陣列相關的物件時,又不小心忘了寫 Block 的話:
[1,2,3].each
=> #<Enumerator: [1, 2, 3]:each>
就會出現這個 Enumerator
! 可是···這是什麼意思?還是不懂。
沒關係把 Enumerator
放一邊,先來看看 Enumerable
能不能輔助我理解。
雖然和上一個概念相比,似乎只有單字詞性的變化,不過 Enumerable
的概念明確許多。
首先,Enumerable
是一種模組(Module),又可以稱為「列舉」,來瞧瞧 Ruby 官方文件的定義:
列舉提供陣列和雜湊搜尋、排序或轉換集合內元素的功能。而陣列或雜湊必須各自提供一個方法,該方法可以產生集合的連續成員···(?)
簡單來說,像是 each
, select
, map
, match
, sort
, grep
這些常用的方法都屬於 Enumerable
的範疇。
詳細內容請參考 Ruby-Doc Module: Enumerable
接下來介紹外部迭代器(External Iterator)
大部分時候我們都在做的是 Internal Iterator
像是平常在丟迴圈,或是上在介紹的陣列方法,都屬於 Internal Iterator
,譬如想從一個陣列中選取一些元素:
list = [1, 2, 3, 4]
list.select do |n|
n > 2
end
#=> [3, 4]
不過,既然有 Internal
,也就有 External
,Internal Iterator
是由陣列或雜湊這類的集合物件控制,而 External Iterator
則是由外部來控制,像是:
icons = %w[up down].to_enum(:cycle)
list = [1, 2, 3, 4, 5]
list.each do
puts icons.next
end
# =>
up
down
up
down
up
=> [1, 2, 3, 4, 5]
在這段程式碼裡,icons
被指定使用 cycle
方式在做迭代,所以當 next
到最後一個元素,下一次的 next
就會從頭再來過。
我這邊引用五倍紅寶石 DC 助教的原話:
Enumerator
最簡單的解釋是Enumerable
加上External Iteration
,而Enumerator
與Enumerable
的合作方式是前者負責產生、儲存資料,『需要時』再以後者的方法運用。
譬如:
list = [1,2,3].each
#=> #<Enumerator: [1, 2, 3]:each>
list.select { |x| x.odd? }
#=> [1, 3]
除了這種彈性的用法之外,Enumerator
的另一個特性是能把物件不斷串起來,以最近超紅的電影《天能》為例:
'TENET'.split('').reverse_each.with_index(1) do |word, index|
puts "#{word}"
end
T
E
N
E
T
=> ["T", "E", "N", "E", "T"]
果然是天能!時光回溯!
Enumerator
的概念不是很好理解,在尋找文獻和研究的過程中不斷撞牆,似乎勉勉強強地看懂了一些,但仍拼湊不出全貌,不過身為工程師,主動接觸一些不熟悉的概念是應該的。
之後的文章應該會放在 Medium 或是自己架的部落格,期許往後的路上還要學得更多,並時常接觸自己不熟悉的領域以及運用所學,天啊!這種既掙扎又興奮的感覺真是太棒了!
那,鐵人賽就先到這邊啦!
在出發的那一刻,我們就已經得到 ONEPIECE 了!
恭喜完賽!每天期待Andrew的ONE PIECE梗搭配Ruby的日子很有趣XDD
謝謝追蹤XDD
其實每天想要放什麼梗比寫文章的時間還多呢(?)