2012-10-06 202 views
1

我正在用Ruby做SaaS課程。在練習中,我被要求通過使用迭代器,塊和屈服來計算兩個序列的笛卡爾乘積。Ruby的例子說明?

我結束了這個,純粹的猜測和錯誤,它似乎工作。但我不確定如何。我似乎瞭解基本塊和產量使用情況,但是這?一點也不。

class CartProd 
    include Enumerable 
    def initialize(a,b) 
     @a = a 
     @b = b 
    end 
    def each 
     @a.each{|ae| 
       @b.each{|be| 
         yield [ae,be] 
       } 
     } 
    end 
end 

對像我這樣的noob有些解釋嗎?

(PS:我改變所需的類名CartProd所以人在做的過程中不能找到這麼容易Google上搜尋它的響應)

+0

備註:類變量@@ a和@@ b是有害的(嘗試使用兩個實例)。它們應該被@a和@b取代。 – steenslag

+0

謝謝,我會糾正它。所以@@定義了類變量和@實例變量。 –

+0

順便說一句,'包含Enumerable'行是不必要的。 – manzoid

回答

0

究竟你這裏不明白嗎?你已經做了一個迭代器,它產生了所有可能的元素對。如果你通過CartProd#each一個塊,它將被執行a.length*b.length次。這就像有兩個不同的for循環以任何其他編程語言摺疊成另一個循環。

+1

也許我不明白什麼產量正在那裏做 –

+0

它只是執行一個塊,如果你的方法調用有一個。您在yield調用中指定的任何參數都將傳遞給block。 – Anton

+0

'yield [ae,be]'通知調用代碼返回值是'[ae,be]'。詳細閱讀[使用可枚舉模塊](http://ruby.about.com/od/advancedruby/ss/Using-The-Enumerable-Module.htm)應該可以幫助您瞭解該示例的工作方式。 –

0

yield只是將控制權交給(產生)控制到已作爲方法調用的一部分傳入的代碼塊。 yield關鍵字後的值作爲參數傳遞到塊中。一旦塊完成執行後,它就回傳控制權。

所以,在你的榜樣,你可以調用#each這樣的:

CartProd.new([1, 2], [3, 4]).each do |pair| 
    # control is yielded to this block 
    p pair 
    # control is returned at end of block 
end 

這將輸出每對值。

7

讓我們一步一步來構建。我們將通過從類上下文中取出來簡化一些事情。

對於這個例子,直覺上認爲迭代器是一個更強大的替代傳統的for循環。

所以首先這裏有一個for循環版本:

seq1 = (0..2) 
seq2 = (0..2) 
for x in seq1 
    for y in seq2 
    p [x,y] # shorthand for puts [x, y].inspect 
    end 
end 

現在讓我們來替換成更Ruby的成語迭代式的,明確供應區塊執行命令(即do...end塊):

seq1.each do |x| 
    seq2.each do |y| 
    p [x,y] 
    end 
end 

到目前爲止,這麼好,你已經打印出你的笛卡爾產品。現在您的任務也會要求您使用yieldyield的要點是「產生執行」,即臨時將控制傳遞給另一個代碼塊(可選地傳遞一個或多個參數)。

所以,雖然它不是這個玩具例子實際上必要的,而不是直接打印像上面的值,可以yield的價值,並讓來電者提供接受該值並打印出來,而不是塊。

這可能看起來像這樣:

def prod(seq1, seq2) 
    seq1.each do |x| 
     seq2.each do |y| 
     yield [x,y] 
     end 
    end 
    end 

可贖回這樣的:

prod (1..2), (1..2) do |prod| p prod end 

yield提供用於內循環的每個運行中的產品,並且得到的值由塊印刷由主叫方提供。

+0

只需添加:一個簡單的寫法是'yield seq1.product(seq2)' – Anorov