2011-11-12 111 views
3

如何將實例變量作爲參數傳遞給塊?塊中的實例變量

這在Ruby 1.9中不起作用(形式參數不能是實例變量)。

awesome do |foo, @bar| 
    puts 'yay' 
end 

回答

2

有3種情況在這裏這可能是相關的:

  • awesome2使用引用實例變量(本例中的塊的定義者的實例變量
  • 定義者的實例變量這個塊使用實例變量作爲參數給接收者(沒有機會把它作爲塊的參數)這是awesome的使用
  • 給出實例變量作爲參數的塊的用戶的實例變量到塊,這是的用法。

因此,讓我們試着實現這兩個例子來看看它們。的例子是冗長,相關線路有:

  • awesome獲取實例變量作爲參數,然後將其在該塊
  • awesome2得不到實例變量的呼叫所使用的接收器,它被結合Sender#use_in_block。接收方沒有機會改變這種綁定。
  • awesome3獲取發送者的實例變量,但使用它自己的實例變量調用塊

所以這取決於你想達到什麼,這三個中的一個是更好的解決方案。

class Sender 
    attr_accessor :send_var 
    def call_a_block(var) 
    rec = Receiver.new(5) 
    @my_var = var 
    res = rec.awesome(@my_var) do |arg1| 
     arg1 + 3 
    end 
    res2 = rec.awesome3(@my_var) do |arg1| 
     arg1 + 3 
    end 
    p "Result of calling awesome with: 3 and #{@my_var} is #{res}" 
    p "Result of calling awesome3 with: 3 and #{@my_var} is #{res2}" 
    end 
    def use_in_block(var) 
    rec = Receiver.new(6) 
    @my_var = var 
    res = rec.awesome2 do 
     4 + @my_var 
    end 
    p "Result of calling awesome2 with: 4 and #{@my_var} is #{res}" 
    end 
end 

class Receiver 
    attr_accessor :rec_var 
    def initialize(var) 
    @rec_var = var 
    end 
    def awesome(arg1) 
    res = yield(arg1) 
    res * 2 
    end 
    def awesome3(arg1) 
    res = yield(@rec_var) 
    res * 2 
    end 
    def awesome2 
    res = yield 
    res * 2 
    end 
end 

s = Sender.new 
s.call_a_block(7) 
s.call_a_block(20) 
s.use_in_block(7) 
s.use_in_block(20) 

結果是:

c:\Temp>ruby call.rb 

"Result of calling awesome with: 3 and 7 is 20" 
"Result of calling awesome3 with: 3 and 7 is 16" 
"Result of calling awesome with: 3 and 20 is 46" 
"Result of calling awesome3 with: 3 and 20 is 16" 
"Result of calling awesome2 with: 4 and 7 is 22" 
"Result of calling awesome2 with: 4 and 20 is 48" 
+0

感謝您的解釋。其他人可能也想閱讀這個[簡介](http://rubylearning.com/satishtalim/ruby_blocks.html)。我的問題不是這個,所以我問了一個新問題。 – m33lky

+0

另外,這是一個解決方案:'[1,2,3] .each {| bar | @ bar = bar}'取自[here](http://boga.wordpress.com/2008/04/15/ruby-19-porting-notes/)。 – m33lky

4

Ruby 1.9將塊參數作爲本地塊。這也意味着塊參數不能再是全局變量或實例變量。您可以使用封你的目的:

@foo = 10 
1.times do |i| 
    puts @foo 
end 
# => "10" 

UPDATE 而不是使用實例變量,局部變量可以幫助您:

foo = 10 
1.times do |i| 
    puts foo 
end 
# => "10" 

在這種情況下,你不會得到相關的問題代碼在不同上下文中執行。

+0

我不能這樣做。這就是我困惑的原因!看看我的[新問題](http://stackoverflow.com/questions/8107584/cant-access-activerecord-mutators-in-a-block)。 – m33lky

+0

好吧,明白了。我更新了我的帖子並回答了你的問題。 – WarHog