昨天提到的引數有好幾種,今天要來介紹Ruby常用的block引數:『區塊引數』。
區塊是什麼呢?本篇文章只有先撥開一點點它的包裝,更深入的內容還有待之後分享!
這次鐵人賽的主題就是使用區塊的一例子:
times是Integer的實體方法,怪了,我們昨天說過,方法的後面接的應該是個圓括號,圓括號的裡面會放入引數,但這個times方法後面卻接著長得很像雜湊(Hash)的東西,這到底是啥?
好的,先不要把這個跟雜湊搞混了,我們以前在Ruby女孩(11)中提到的雜湊,雜湊是長這樣的:
{:name => "Annie",:age => 99}
或
{name: "Annie", age: 99}
很明顯你在雜湊中會看到一對一對的鍵(Key)與值(Value),與Numeric、String與Array一樣都是Ruby中的資料型別。但今天所要認識的『區塊(block)』,它並不是另一種資料型別,它是迭代器的基礎,我們接下來會好好認識它是怎麼運作,而方法要如何調用它?
※ 區塊的語法
1. 區塊不能單獨存在,它一定要伴隨著方法調用。
2. 可以用大括號{}或是do和end當作區塊的起始與終止。
3. 但左括號{或do,一定要跟方法名稱放在同一列。
4. 有一慣例,當區塊方法只有一行時,使用{};若超過一行,則使用do/end。
1.upto(10) { |x| puts x }
或
1.upto(10) do |x|
puts x
end
5. 如果想省略圓括號,要小心!請看以下範例:
1.upto(10) {|x| puts x} #正常執行
1.upto 10 do |x| puts x end #正常執行
1.upto 10 {|x| puts x} #SyntaxError
區塊會找緊接著它的方法試圖傳進去,第三種會出現SyntaxError,就是因為它以為緊跟著它的方法是10,才會噴錯!所以若想省略方法的圓括號,請改以do/end撰寫。不然就不要省略!!
6. 區塊本身也可以類似方法而有多個參數,例如:
test.each { |x,y,z| puts "#{x}、#{y}、#{z}" }
7. 區塊本身的參數也有一慣例寫法,會跟左括號{或do寫在同一行。
OK,看完區塊的基本規則,我們來了解一下該如何在方法的引數中傳入區塊。
※ 傳遞區塊引數
由於區塊是不具名稱的,他們的調用是要前綴一個『&』符號,而且規定一定要寫在引數的最後一個!實際使用的方式如下:
def test(a,b,*c,&d)
puts "a=#{a}"
puts "b=#{b}"
puts "c=#{c}"
d.call(5)
end
test(1,2,3,4,5){|n| n.times{puts "ruby"}}
a=1
b=2
c=[3, 4, 5]
ruby
ruby
ruby
ruby
ruby
你可以注意到,我們在方法後面直接丟入了一個區塊作為&d的引數,並且在方法中,用.call來給予區塊本身的區塊參數!那.call這個方法是誰的方法呢?我們可以用這個方法看看區塊到底是誰?
def who_am_i(&block)
"我其實是#{block.class}"
end
who_am_i{}
=> "我其實是Proc"
好像解謎一樣,一層一層把區塊的秘密掀出來XD原來區塊是Proc,Proc和Lambda是另一組容易被搞混的詞,這個部分我得好好吸收一下才知道怎麼寫出來不會誤導大家!有待明天揭曉XD
最後補充一個書上目前沒看到的傳遞引數的方式:
def sum(a, *b, **c, &d)
puts "a=#{a}"
puts "b=#{b}"
puts "c=#{c}"
d.call(100)
end
sum(1,2,3,4,5,x:6,y:7) { |x| puts x }
a=1
b=[2, 3, 4, 5]
c={:x=>6, :y=>7}
100
有看見上面的c前綴的是『**』,與『*』不同的是,『**』可以傳進雜湊的值,也因此你才可以看到上面puts c之後的結果!
=================================================
28天!
“Decide that you want it more than you are afraid of it.”
雖然讀的內容越來越深,但想學的心還是大於害怕!加油加油!