2012-12-19 71 views
5

這可能不是你應該在家裏嘗試,但出於某種原因,我嘗試在Ruby中創建一個方法數組。Ruby:數組元素的方法 - 它們是如何工作的?

我首先定義了兩種方法。

irb(main):001:0> def test1 
irb(main):002:1> puts "test!" 
irb(main):003:1> end 
=> nil 
irb(main):004:0> def test2 
irb(main):005:1> puts "test2!" 
irb(main):006:1> end 
=> nil 

當您嘗試將它放入實際數組時,會發生奇怪的事情。它似乎運行這兩種方法。

irb(main):007:0> array = [test1, test2] 
test! 
test2! 
=> [nil, nil] 

然後,數組是空的。

irb(main):008:0> puts array 


=> nil 

有人可以向我解釋爲什麼它運行的方法?除此之外,整個練習都嚴重需要驅魔人嗎?

回答

14

你在數組中存儲的內容是調用方法的結果,而不是方法本身。

def test1 
    puts "foo!" 
end 

def test2 
    puts "bar!" 
end 

您可以存儲到這樣的實際方法的引用:

> arr = [method(:test1), method(:test2)] 
# => [#<Method: Object#test1>, #<Method: Object#test2>] 

之後,你可以調用引用的方法是這樣的:

> arr.each {|m| m.call } 
foo! 
bar! 
+0

哦,這是可能的。太好了! – Nekkoru

1

如果你有一個square方法,想要創建的2和4的平方值的數組,你會

array = [square(2), square(4)] 

在這裏,你正在做同樣的事情,但你的測試方法不要寫不會返回任何東西,這就是爲什麼你的最終array看起來是空的(實際上,它包含[nil, nil])。

+0

這種情況下的方法定義返回'nil',如圖所示。 OP說它變空了是錯誤的;它不是。空白行被打印,表示數組所具有的兩個「nil」實例。 – sawa

+0

@sawa你說得對,我的回答不夠精確。我編輯過。 – alestanis

1

您的數組永遠不會包含除兩個零值之外的任何內容。我在評估時通過放置字符串來欺騙你。但是每個函數的返回值仍然是零。

1

您的代碼運行這兩種方法,因爲當您說「test1」和「test2」時實際調用方法 - 括號對於ruby方法調用是可選的。

由於你的兩個方法都只包含一個「puts」,它返回nil,所以你的結果數組只是兩個nils的數組。

3

@alestanis解釋的原因很好。如果你想儲存方法,那麼你可以做什麼拉斯Haugseth說,或者你可以做folllowing:

test1 = Proc.new { puts "test!" } 
test2 = Proc.new { puts "test2!" } 
a = [test1, test2] 

這可能使你的代碼更易讀。

這是一個irb運行。

1.9.3p194 :009 > test1 = Proc.new { puts "test!" } 
=> #<Proc:[email protected](irb):9> 
1.9.3p194 :010 > test2 = Proc.new { puts "test2!" } 
=> #<Proc:0x00000002792[email protected](irb):10> 
1.9.3p194 :011 > a = [test1, test2] 
=> [#<Proc:[email protected](irb):9>, #<Proc:[email protected](irb):10>] 
0

這是我的兩便士的價值。基於已發佈的解決方案,這是一個工作示例的例子。這裏可能有些方便的是它包含方法參數和self(它指的是實例化時的PromotionalRules類的實例)以及符號數組,這些都是整齊的 - 我從Ruby文檔在#send方法here上。希望這可以幫助別人!

class PromotionalRules 
    PROMOTIONS = [:lavender_heart_promotion, :ten_percent_discount] 

    def apply_promotions total, basket 
    @total = total 

    if PROMOTIONS.count > 0 
     PROMOTIONS.each { |promotion| @total = self.send promotion, @total, basket } 
    end 

    @total.round(2) 
    end 

    def lavender_heart_promotion total, basket 
    if two_or_more_lavender_hearts? basket 
     basket.map { |item| total -= 0.75 if item == 001 } 
    end 
    total 
    end 

    def two_or_more_lavender_hearts? basket 
    n = 0 
    basket.each do |item| 
     n += 1 if item == 001 
    end 
    n >= 2 
    end 

    def ten_percent_discount total, *arg 
    if total > 60.00 
     total = total - total/10 
    end 
    total 
    end 
end 

感謝大家的幫助。我喜歡編碼的開源特性 - 隨着人們遍歷彼此的解決方案,線程變得越來越好!

相關問題