2010年4月18日 星期日

Ruby 快速筆記: Block and Iterator

Block

Block是相當特別的東西,在某些語言裡block被稱做closure,
先看個例子,我需要連續打印"hello"五次,那麼這樣寫就行:
5.times { print "hello" }
# hellohellohellohellohello
Ruby是個純OO語言,所以數字5也有函數可以呼叫,times就是其中之一。
這個例子最常被拿來說嘴Ruby有多麼簡潔。

Block可以看作某種匿名的函數,或者是...一沱程式碼。
{ print "hello" }    # 這就是一個block
Block不能單獨存在,必須掛在function call後面,以供function使用,
例如它附掛在times這個函數後面,而5.times的功用就是連續執行這個block五次!
這程式可讀性實在高。(有什麼比5.times更接近五次?)

Iterator

那這個Block有什麼實際的用途呢?
Ruby裡的Iterator就是用Block來達成。
例如
a = ["apple", "banana", "orange"]  
這是一個字串Array,我們想要遍訪a的各個元素,該怎麼做呢?
a.each { |s| puts s+'is fruit' }

# 執行結果
# apple is fruit
# banana is fruit
# orange is fruit
a.each 這個方法會遍訪array的各個元素(此處就是水果的名稱),並且對每個元素就都調用一次Block。Block開頭處的 |變數| ,就代表當下的的陣列元素,例如上例的 |s|就是各個水果的名稱。這個例子我們將陣列內水果的名稱都打印出來。

以下還有很多例子
(1..100).each { |i| puts i }    # 依序印出數字1~100
('a'..'z').each { |c| puts c }  # 依序印出26個英文字母
[1,2,3,4,5].map { |e| e*e }     # [1,4,9,16,25] 陣列每個元素都取平方

open('aaa.txt').each do |line|  # 檔案逐行讀取
    puts line
end
Block算是相當便捷的用法。

最後一提,Block其實有兩種寫法:
1. do ... end
2. {...}
當然效果是一模一樣。
a.each { |e| puts e }

a.each do |e|
    puts e
end
慣例是block內有多行程式碼用do end,若單行則用{}較緊湊。