鐵 人
Ruby女孩(28):慢慢打開區塊引數的包裝
2014.Oct.28

昨天提到的引數有好幾種,今天要來介紹Ruby 常用的block 引數:『區塊引數』

區塊是什麼呢?本篇文章只有先撥開一點點它的包裝,更深入的內容還有待之後分享!

這次鐵人賽的主題就是使用區塊的一例子:

10萬.times { puts "為什麼?" }

.times是Integer的實體方法,怪了,我們昨天說過,方法的後面接的應該是個( )( )的裡面會放入引數,但這個.times方法後面卻接著長得很像雜湊(Hash)的東西,這到底是啥?

好的,先不要把這個跟雜湊搞混了,我們以前在Ruby女孩(11)中提到的雜湊,雜湊是長這樣的:

{:name => "Annie",:age => 99}  

{name: "Annie", age: 99}  

很明顯你在雜湊中會看到一對一對的鍵(Key)值(Value),與Numeric、String與Array一樣都是Ruby中的資料型別。但今天所要認識的『區塊(block)』,它並不是另一種資料型別,它是迭代器的基礎,我們接下來會好好認識它是怎麼運作,而方法要如何調用它?

區塊的語法

  1. 區塊不能單獨存在,它一定要伴隨著方法調用。
  2. 可以用大括號{ }或是doend當作區塊的起始與終止。
  3. 但左括號{do,一定要跟方法名稱放在同一列。
  4. 有一慣例,當區塊方法只有一行時,使用{};若超過一行,則使用do/end
1.upto(10) { |x| puts x }  

1.upto(10) do |x|  
  puts x  
end  
  1. 如果想省略圓括號,要小心!請看以下範例:
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撰寫。不然就不要省略!!

  1. 區塊本身也可以類似方法而有多個參數,例如:
test.each { |x,y,z| puts "#{x}#{y}#{z}" }  
  1. 區塊本身的參數也有一慣例寫法,會跟左括號{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 原來區塊是ProcProcLambda是另一組容易被搞混的詞,這個部分我得好好吸收一下才知道怎麼寫出來不會誤導大家!有待明天揭曉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.”

雖然讀的內容越來越深,但想學的心還是大於害怕!加油加油!

Ruby女孩(29):揭開區塊的面紗-Proc、lambda
2014.Oct.29
Ruby女孩(27):方法的引數傳遞方式,你覺得很簡單嗎?進來小試身手看看XD
2014.Oct.27
comments powered by Disqus